Hey Hype Users,
I've crafted a simple CMS that uses JSON Schema to create dynamic forms, with the output saved into a data.json file. The demo is live but with saving disabled to prevent any misuse and ensure the demo data remains clean.
Demo SimpleCMS
Password: test
JSON: https://playground.maxziebell.de/Hype/SimpleCMS/demo1/data.json is the result
Thinking ahead, I might externalize the JSON schema into its own file and introduce an option to write JSON directly into a selected HTML file to bypass the Fetch step.
I’d appreciate your thoughts on this... Feedback is welcome!
Cheers and happy holidays
<?php
/*
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
*/
session_start();
// Define a password for simplicity. This should be securely hashed in a real-world scenario.
define('PASSWORD', 'test');
// Check for logout action
if (isset($_GET['action']) && $_GET['action'] === 'logout') {
unset($_SESSION['logged_in']);
}
// Check if the user is logged in
$loggedIn = isset($_SESSION['logged_in']) && $_SESSION['logged_in'] === true;
// Start of the form processing code
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Check for login attempt
if (!$loggedIn && isset($_POST['password'])) {
if ($_POST['password'] === PASSWORD) {
$_SESSION['logged_in'] = true;
// Redirect to avoid resubmission on refresh
header('Location: ' . $_SERVER['PHP_SELF']);
exit;
} else {
$error = "Incorrect password.";
}
}
// Check for data submission when logged in
if ($loggedIn && isset($_POST['jsonData'])) {
// The form should submit a JSON string under the name 'jsonData'
file_put_contents('data.json', $_POST['jsonData']);
// Redirect back to the same page to avoid form resubmission issues
header('Location: ' . $_SERVER['PHP_SELF']);
exit;
}
}
// Load data if available and user is logged in
$dataJson = $loggedIn && file_exists('data.json') ? json_decode(file_get_contents('data.json'), true) : null;
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SimpleCMS</title>
<style>
body { font-family: Arial, sans-serif; }
.form-container { max-width: 750px; margin: auto; }
#jsonForm h4 { margin: 40px 0px 0px 0px; }
#jsonForm > .je-object__container > .je-object__title { margin-left: 15px; }
.sticky-header { position: sticky; top: 0; background-color: white; padding: 10px 0px; border-bottom: 1px solid #ccc; z-index: 1000; }
.button-container { display: grid; grid-template-columns: 1fr 1fr; }
.left-btn { justify-self: start; }
.right-btn { justify-self: end; }
.submit-btn, .logout-btn { margin: 0 10px; }
</style>
<link rel="stylesheet" href="https://unpkg.com/spectre.css/dist/spectre.min.css">
<link rel="stylesheet" href="https://unpkg.com/spectre.css/dist/spectre-exp.min.css">
<link rel="stylesheet" href="https://unpkg.com/spectre.css/dist/spectre-icons.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/json-editor/2.5.4/jsoneditor.min.js"></script>
</head>
<body>
<?php if (!$loggedIn): ?>
<div class="form-container">
<form id="loginForm" action="" method="post" class="form-horizontal">
<div class="container grid-lg" style="margin-top: 50px;">
<div class="columns">
<!-- Centering the form on the grid -->
<div class="column col-4 col-mx-auto">
<form id="loginForm" action="" method="post">
<div class="form-group">
<label for="password" class="form-label">Password:</label>
<input type="password" id="password" name="password" class="form-input" >
</div>
<div class="form-group">
<!-- Using 'col-mx-auto' to center the button -->
<button type="submit" class="btn btn-primary btn-block">Login</button>
</div>
</form>
</div>
</div>
</div>
</form>
</div>
<?php else: ?>
<div class="form-container">
<form id="jsonForm" method="post" action="">
<input type="hidden" name="jsonData" value="" />
<!-- Sticky header container for the buttons -->
<div class="sticky-header">
<div class="button-container">
<button type="submit" class="btn btn-sm submit-btn left-btn">Save</button>
<button type="button" onclick="logout();" class="btn btn-sm logout-btn right-btn">Logout</button>
</div>
</div>
</form>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Define the JSON Schema
const schema = {
"title": "Custom Data for Hype Reactive Content",
"type": "object",
"required": ["name", "age", "date", "favorite_color", "gender", "location", "pets", "file"],
"properties": {
"name": { "type": "string", "description": "First and Last name", "minLength": 4, "default": "Jeremy Dorn" },
"age": { "type": "integer", "default": 25, "minimum": 18, "maximum": 99 },
"favorite_color": { "type": "string", "format": "color", "title": "favorite color", "default": "#ffa500" },
"gender": { "type": "string", "enum": ["male", "female"], "default": "male" },
"date": { "type": "string", "format": "date" },
"location": {
"type": "object",
"properties": {
"city": { "type": "string" },
"state": { "type": "string" },
"citystate": { "type": "string", "default": "San Francisco, CA" }
},
"required": ["city", "state"]
},
"file": {
"type": "string",
"title": "file",
"media": {
"binaryEncoding": "base64",
"type": "img/png"
},
"options": {
"grid_columns": 6,
"multiple": true,
}
},
"description": {
"type": "string",
"title": "Description",
"options": {
"grid_columns": 6
}
},
"pets": {
"type": "array",
"format": "table",
"items": {
"type": "object",
"properties": {
"type": { "type": "string" },
"name": { "type": "string" }
},
"required": ["type", "name"]
}
},
}
};
// Initialize the editor with the schema
const editor = new JSONEditor(document.getElementById('jsonForm'), {
schema: schema,
disable_edit_json: true,
disable_properties: true,
disable_collapse: true,
display_required_only: false,
theme: 'spectre',
iconlib: 'spectre',
startval: <?php echo $dataJson ? json_encode($dataJson) : '{}'; ?>
});
document.getElementById('jsonForm').addEventListener('submit', function(event) {
// JSON Editor instance
const value = editor.getValue();
const hiddenInput = document.querySelector('input[name="jsonData"]');
hiddenInput.value = JSON.stringify(value);
});
window.logout = function() {
window.location = '?action=logout';
}
// Add the saved data to the form if logged in
<?php if ($dataJson): ?>
editor.setValue(<?php echo json_encode($dataJson); ?>);
<?php endif; ?>
});
</script>
<?php endif; ?>
</body>
</html>