v0.1: replace shell-rendered site with Grav-native pages + theme

- Drop site/ + RenderSite.sh: repo now carries grav/user/pages as
  native Grav markdown pages (home/services/terms/sign/execution)
- Add knel-contract theme: inherits quark2 via stream fallback, adds
  sign.html.twig (Twig) driving the DocuSeal flow through the APISIX
  gateway; esign wiring lives in the theme yaml for forks to retarget
- CreateDocument.sh refreshes the Grav services page from the
  rendered catalogs instead of invoking the removed site renderer

Ticket: https://projects.knownelement.com/issues/924
This commit is contained in:
2026-09-07 14:41:50 -05:00
parent 4bc56c83d3
commit 16528ff813
13 changed files with 131 additions and 189 deletions
+13 -2
View File
@@ -16,5 +16,16 @@ bash RenderCSVToMarkdown.sh
echo "Putting it all together..." echo "Putting it all together..."
bash RenderBook.sh bash RenderBook.sh
echo "Rendering Grav site..." echo "Refreshing the Grav services page from the rendered catalogs..."
bash RenderSite.sh {
echo "---"
echo "title: 'Services'"
echo "visible: true"
echo "menu: Services"
echo "---"
cat src/services-general.md
for f in cloudron-all cloudron-lob coolify-techops-all coolify-techops-lob coolify-randd-all coolify-randd-lob kneldc-all kneldc-lob; do
echo
cat src/services-$f.md
done
} > grav/user/pages/02.services/default.md
-74
View File
@@ -1,74 +0,0 @@
#!/bin/bash
# Render the Grav site pages (site/) from the rendered contract (src/)
# and the service CSVs. Run after RenderTemplates.sh + RenderCSVToMarkdown.sh
# (CreateDocument.sh does all of it in order).
set -euo pipefail
SITE_DIR="site"
TMP=$(mktemp -d)
trap 'rm -rf "$TMP"' EXIT
# --- 01.home: introduction + parties -------------------------------
{
echo "---"
echo "title: 'Known Element Enterprises LLC — Services Contract'"
echo "visible: true"
echo "---"
cat src/introduction.md
echo
cat src/parties.md
} > "$SITE_DIR/01.home/page.md"
# --- 02.services: all service catalogs ------------------------------
{
echo "---"
echo "title: 'Services Offered'"
echo "visible: true"
echo "---"
cat src/services-general.md
echo
cat src/services-cloudron-all.md
echo
cat src/services-cloudron-lob.md
echo
cat src/services-coolify-techops-all.md
echo
cat src/services-coolify-techops-lob.md
echo
cat src/services-coolify-randd-all.md
echo
cat src/services-coolify-randd-lob.md
echo
cat src/services-kneldc-all.md
echo
cat src/services-kneldc-lob.md
} > "$SITE_DIR/02.services/page.md"
# --- 03.terms: legal sections ----------------------------------------
{
echo "---"
echo "title: 'Terms and Conditions'"
echo "visible: true"
echo "---"
cat src/legal-definitions.md
echo
cat src/legal-dispute-resolution.md
echo
cat src/legal-general-terms.md
} > "$SITE_DIR/03.terms/page.md"
# --- 04.sign: e-signature via DocuSeal through the APISIX gateway ----
MUSTACHE_PATH="vendor/git.knownelement.com/ExternalVendorCode/mo/mo"
bash "$MUSTACHE_PATH" contract-inputs/sign-electronic.md > "$SITE_DIR/04.sign/page.md"
# --- 05.execution: signature blocks ----------------------------------
{
echo "---"
echo "title: 'Execution'"
echo "visible: true"
echo "---"
cat src/signatures.md
} > "$SITE_DIR/05.execution/page.md"
echo "Site rendered into $SITE_DIR"
-55
View File
@@ -1,55 +0,0 @@
---
title: 'Sign Electronically'
visible: true
---
## Sign this contract electronically
This contract can be executed electronically via the KNEL DocuSeal e-signature platform, reached through the KNEL APISIX API gateway. Enter the signer's details below; DocuSeal will email a signing link.
<form id="esign-form" onsubmit="return esignSubmit(event)">
<label for="esign-name">Full name</label>
<input type="text" id="esign-name" name="name" required style="display:block;margin-bottom:8px;min-width:280px;padding:6px;">
<label for="esign-email">Email address</label>
<input type="email" id="esign-email" name="email" required style="display:block;margin-bottom:12px;min-width:280px;padding:6px;">
<label for="esign-entity">Entity (Party 2)</label>
<input type="text" id="esign-entity" name="entity" required style="display:block;margin-bottom:12px;min-width:280px;padding:6px;">
<button type="submit" style="padding:8px 16px;">Request signature link</button>
</form>
<p id="esign-status" style="margin-top:12px;"></p>
<script>
function esignSubmit(ev) {
ev.preventDefault();
var status = document.getElementById('esign-status');
status.textContent = 'Requesting signing link…';
var name = document.getElementById('esign-name').value;
var email = document.getElementById('esign-email').value;
var entity = document.getElementById('esign-entity').value;
fetch('{{ESIGN_API_URL}}', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
template_id: Number('{{ESIGN_TEMPLATE_ID}}'),
submitters: [
{email: email, name: name, role: 'First Party'},
{email: email, name: name + ' (' + entity + ')', role: 'Second Party', is_invited: false}
]
})
}).then(function (r) {
if (!r.ok) throw new Error('gateway returned ' + r.status);
return r.json();
}).then(function (data) {
var slug = data.submitters && data.submitters[0] && data.submitters[0].slug;
if (slug) {
window.location.href = 'https://esign.knownelement.com/s/' + slug;
} else {
status.textContent = 'Signing request created. Check ' + email + ' for the signing link.';
}
}).catch(function (e) {
status.textContent = 'Could not create the signing request (' + e.message + '). Contact KNEL helpdesk.';
});
return false;
}
</script>
@@ -1,6 +1,7 @@
--- ---
title: 'Known Element Enterprises LLC — Services Contract' title: 'KEE Services Contract'
visible: true visible: true
menu: Home
--- ---
## Introduction ## Introduction
@@ -44,4 +45,5 @@ Known Element Enterprises LLC
### Party 2 ### Party 2
TSYS Group Component TSYS Group Component
Explore the [services offered](/services), the [terms and conditions](/terms), and [sign electronically](/sign).
@@ -1,6 +1,7 @@
--- ---
title: 'Services Offered' title: 'Services'
visible: true visible: true
menu: Services
--- ---
# General Services Offered # General Services Offered
@@ -1,6 +1,7 @@
--- ---
title: 'Terms and Conditions' title: 'Terms and Conditions'
visible: true visible: true
menu: Terms
--- ---
## Definitions ## Definitions
+8
View File
@@ -0,0 +1,8 @@
---
title: 'Sign Electronically'
visible: true
menu: Sign
template: sign
---
This contract may be executed electronically via the KNEL DocuSeal e-signature platform, reached through the KNEL APISIX API gateway. Enter the signer's details below; DocuSeal will issue a signing session.
@@ -1,6 +1,7 @@
--- ---
title: 'Execution' title: 'Execution'
visible: true visible: true
menu: Execution
--- ---
## Execution ## Execution
@@ -0,0 +1,6 @@
name: knel-contract
slug: knel-contract
type: theme
version: 0.1.0
description: KNEL services contract site theme
author: KNEL
@@ -0,0 +1,17 @@
enabled: true
# Any quark2 template not overridden here falls through to quark2
streams:
schemes:
theme:
type: ReadOnlyStream
prefixes:
'':
- user/themes/knel-contract
- user/themes/quark2
# E-sign wiring (forks: point these at your own gateway/template)
esign:
api_url: 'https://apigw.knownelement.com/contract-sign/api/submissions'
sign_url: 'https://esign.knownelement.com'
template_id: '2'
@@ -0,0 +1,69 @@
{% extends 'partials/base.html.twig' %}
{% block content %}
<div class="sign-page">
{{ page.content|raw }}
<style>
.sign-page form { max-width: 32rem; }
.sign-page label { display: block; margin: 0.75rem 0 0.25rem; font-weight: 600; }
.sign-page input { display: block; width: 100%; padding: 0.5rem; border: 1px solid #ccc; border-radius: 4px; }
.sign-page button { margin-top: 1rem; padding: 0.6rem 1.4rem; cursor: pointer; }
</style>
<form id="esign-form">
<label for="esign-name">Full name</label>
<input type="text" id="esign-name" name="name" required>
<label for="esign-email">Email address</label>
<input type="email" id="esign-email" name="email" required>
<label for="esign-entity">Entity (Party 2)</label>
<input type="text" id="esign-entity" name="entity" required>
<button type="submit">Request signature link</button>
</form>
<p id="esign-status"></p>
</div>
<script>
(function () {
var form = document.getElementById('esign-form');
var status = document.getElementById('esign-status');
var config = {{ grav.config.themes['knel-contract'].esign|json_encode|raw }};
form.addEventListener('submit', function (ev) {
ev.preventDefault();
status.textContent = 'Requesting signing link…';
var name = document.getElementById('esign-name').value;
var email = document.getElementById('esign-email').value;
var entity = document.getElementById('esign-entity').value;
fetch(config.api_url, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
template_id: Number(config.template_id),
send_email: false,
submitters: [
{role: 'First Party', name: name, email: email},
{role: 'Second Party', name: name + ' (' + entity + ')', email: email}
]
})
}).then(function (r) {
if (!r.ok) { throw new Error('gateway returned ' + r.status); }
return r.json();
}).then(function (data) {
var slug = data.submitters && data.submitters[0] && data.submitters[0].slug;
if (slug) {
window.location.href = config.sign_url + '/s/' + slug;
} else {
status.textContent = 'Signing request created. Check ' + email + ' for the signing link.';
}
}).catch(function (e) {
status.textContent = 'Could not create the signing request (' + e.message + '). Contact the KNEL helpdesk.';
});
});
})();
</script>
{% endblock %}
+10
View File
@@ -0,0 +1,10 @@
slug: knel-contract
name: 'KNEL Contract'
type: theme
version: 0.1.0
description: 'KNEL services contract site. Inherits Quark2; adds the DocuSeal e-sign page template.'
icon: file-text
author:
name: Known Element Enterprises LLC
keywords: contract
license: AGPL-3.0
-55
View File
@@ -1,55 +0,0 @@
---
title: 'Sign Electronically'
visible: true
---
## Sign this contract electronically
This contract can be executed electronically via the KNEL DocuSeal e-signature platform, reached through the KNEL APISIX API gateway. Enter the signer's details below; DocuSeal will email a signing link.
<form id="esign-form" onsubmit="return esignSubmit(event)">
<label for="esign-name">Full name</label>
<input type="text" id="esign-name" name="name" required style="display:block;margin-bottom:8px;min-width:280px;padding:6px;">
<label for="esign-email">Email address</label>
<input type="email" id="esign-email" name="email" required style="display:block;margin-bottom:12px;min-width:280px;padding:6px;">
<label for="esign-entity">Entity (Party 2)</label>
<input type="text" id="esign-entity" name="entity" required style="display:block;margin-bottom:12px;min-width:280px;padding:6px;">
<button type="submit" style="padding:8px 16px;">Request signature link</button>
</form>
<p id="esign-status" style="margin-top:12px;"></p>
<script>
function esignSubmit(ev) {
ev.preventDefault();
var status = document.getElementById('esign-status');
status.textContent = 'Requesting signing link…';
var name = document.getElementById('esign-name').value;
var email = document.getElementById('esign-email').value;
var entity = document.getElementById('esign-entity').value;
fetch('', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
template_id: Number(''),
submitters: [
{email: email, name: name, role: 'First Party'},
{email: email, name: name + ' (' + entity + ')', role: 'Second Party', is_invited: false}
]
})
}).then(function (r) {
if (!r.ok) throw new Error('gateway returned ' + r.status);
return r.json();
}).then(function (data) {
var slug = data.submitters && data.submitters[0] && data.submitters[0].slug;
if (slug) {
window.location.href = 'https://esign.knownelement.com/s/' + slug;
} else {
status.textContent = 'Signing request created. Check ' + email + ' for the signing link.';
}
}).catch(function (e) {
status.textContent = 'Could not create the signing request (' + e.message + '). Contact KNEL helpdesk.';
});
return false;
}
</script>