Add README, customization snapshot, and snapshot/restore tooling

Provisioning now restores all GUI customizations on reset+reprovision:

- create_pod_espocrm.sh: deploy the version-controlled espocrm-custom/ tree
  (CTag entity, layouts, i18n, clientDefs, custom views, custom CSS) into the
  pod, then chown www-data and rebuild. Replaces the earlier inline CSS-only
  step. Adds a live-phase cache rebuild so customizations and the client
  cacheTimestamp are refreshed on every run.
- espocrm-custom/: snapshot of custom/ and client/custom/ (source of truth).
- snapshot_espocrm_custom.sh: refresh the snapshot from a running pod.
- readme.md: usage, first-time host setup, image-update and reset workflows.
- Include the task/instruction notes and plan.md for reference.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
mkt
2026-06-06 16:51:02 +02:00
parent 79ea236da0
commit cebe829dcd
79 changed files with 2064 additions and 45 deletions

View File

@@ -25,6 +25,13 @@ BIND_DIR="$HOME/.local/share/$POD_NAME"
DB_DATA_DIR="$BIND_DIR/mariadb" # -> /var/lib/mysql
ESPO_DATA_DIR="$BIND_DIR/espocrm" # -> /var/www/html
# GUI customizations snapshot, version-controlled in this repo next to the script.
# Deployed into /var/www/html on every provisioning run so a reset+reprovision
# restores all customizations (CTag entity, layouts, i18n, clientDefs, custom
# views, custom CSS, ...). Refresh it after GUI changes with snapshot_espocrm_custom.sh.
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
CUSTOM_SRC="$SCRIPT_DIR/espocrm-custom" # contains custom/ and client/custom/
# systemd --user paths
USER_SYSTEMD_DIR="$HOME/.config/systemd/user"
WEB_UNIT_FILE="$USER_SYSTEMD_DIR/container-${WEB_CTR}.service"
@@ -103,50 +110,22 @@ for i in $(seq 1 90); do
done
echo "EspoCRM responded with HTTP $code (rc=$?)"
# --- GUI customization: variable column widths for Markdown tables -------------
# Core CSS forces `table-layout: fixed; width: 100%` on `.complex-text table`,
# giving every column an equal width. Register a custom CSS file via cssList so
# those tables size columns to content (table-layout: auto). Created by this
# provisioning script (on the persisted bind-mount) so it survives re-runs; the
# rebuild step below refreshes the cached cssList metadata.
podman exec "$WEB_CTR" sh -lc 'mkdir -p /var/www/html/client/custom/css /var/www/html/custom/Espo/Custom/Resources/metadata/app'
podman exec -i "$WEB_CTR" sh -c 'cat > /var/www/html/client/custom/css/table-var-col.css' <<'CSSEOF'
/**
* Variable column widths for Markdown tables in text fields.
*
* EspoCRM core CSS forces `table-layout: fixed; width: 100%` on
* `.complex-text table`, which makes all columns equally wide.
* `auto` lets columns size to content instead.
*
* Registered via custom/Espo/Custom/Resources/metadata/app/client.json (cssList).
*/
.complex-text table {
table-layout: auto !important;
width: auto !important;
max-width: 100% !important;
}
CSSEOF
echo "Wrote client/custom/css/table-var-col.css (rc=$?)"
# Merge the CSS path into cssList (idempotent; preserves other keys/entries and
# keeps "__APPEND__" first). Uses the container's php so no host jq is required.
podman exec "$WEB_CTR" php -r '
$file = "/var/www/html/custom/Espo/Custom/Resources/metadata/app/client.json";
$css = "client/custom/css/table-var-col.css";
$data = is_file($file) ? json_decode(file_get_contents($file), true) : [];
if (!is_array($data)) { $data = []; }
$list = (isset($data["cssList"]) && is_array($data["cssList"])) ? $data["cssList"] : [];
$list = array_values(array_filter($list, function ($x) use ($css) { return $x !== "__APPEND__" && $x !== $css; }));
array_unshift($list, "__APPEND__");
$list[] = $css;
$data["cssList"] = $list;
file_put_contents($file, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n");
'
echo "Registered table-var-col.css in cssList (rc=$?)"
# Match ownership of the other EspoCRM customization files (webserver user).
podman exec "$WEB_CTR" chown -R www-data:www-data /var/www/html/client/custom /var/www/html/custom/Espo/Custom/Resources/metadata
echo "Fixed ownership of customizations (rc=$?)"
# --- Deploy all GUI customizations from the repo snapshot ---------------------
# Copies the version-controlled custom/ and client/custom/ trees into the pod so
# a reset+reprovision restores everything: the CTag entity (controller, scopes,
# recordDefs, i18n), layouts, clientDefs (Tags +button removed, row-actions =
# Unlink only), the signature image-button view, and the table-var-col CSS.
# Extract as container-root (--no-same-owner), then chown to the webserver user.
# The rebuild step below refreshes the cached metadata (entityDefs, cssList, ...).
if [ -d "$CUSTOM_SRC" ]; then
tar -C "$CUSTOM_SRC" -cf - custom client/custom \
| podman exec -i "$WEB_CTR" tar -C /var/www/html -xf - --no-same-owner
echo "Deployed GUI customizations from $CUSTOM_SRC (rc=$?)"
podman exec "$WEB_CTR" chown -R www-data:www-data /var/www/html/custom /var/www/html/client/custom
echo "Fixed ownership of customizations (rc=$?)"
else
echo "WARNING: customization snapshot not found at $CUSTOM_SRC; skipping deploy."
fi
# Rebuild EspoCRM cache so customizations on the persisted bind-mount take effect
# and the client cacheTimestamp is bumped (forces browsers to reload custom views,