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

@@ -0,0 +1,105 @@
### Goal
Restore the image button (`espoImage`) in the EspoCRM **signature** editor toolbar. The signature field uses the core view `views/preferences/fields/signature`, whose `setupToolbar()` overrides the toolbar to `[["style",[…]],["color",["color"]],["height",["height"]],["table",["espoLink"]],["misc",[<codeview>,"fullscreen"]]]` — i.e. it drops the `espoImage` button that the generic wysiwyg field has. We want the image button back **only for the signature field**, without changing anything else.
Do **not** touch other fields, ACLs, the generic wysiwyg editor (email body / templates already have the image button), or any data.
### Environment
- EspoCRM **9.3.8** (Apache variant) runs as a **rootless Podman pod** `espocrm_pod` on this server. Web container is expected to be `espocrm_ctr` (confirm with `podman ps`).
- App root inside the web container: `/var/www/html`, runs as user **`www-data`**.
- Customizations live on the persisted `/var/www/html` bind-mount, same locations as the S47 task:
- Backend metadata: `/var/www/html/custom/Espo/Custom/Resources/metadata/…`
- Frontend custom views: `/var/www/html/client/custom/src/…` (referenced with the `custom:` prefix).
### Mechanism (from 9.3.8 source — confirm against this instance before relying on it)
- The signature field view `client/src/views/preferences/fields/signature.js` extends the wysiwyg field and **overrides** `setupToolbar()`. Its `this.toolbar` contains a group `['table', ['espoLink']]` — the link button but **not** `espoImage`.
- The generic wysiwyg field `client/src/views/fields/wysiwyg.js` registers the upload callback in `enableWysiwygMode()`: `onImageUpload``uploadInlineAttachment(file)` → creates an `Attachment` (`role: 'Inline Attachment'`) and inserts `<img src="?entryPoint=attachment&id=…">`. This callback is present regardless of the toolbar, so as soon as the `espoImage` button is in the toolbar, its upload path produces an attachment.
- `espoImage` is a registered summernote plugin (`client/src/helpers/misc/summernote-custom.js`): its button invokes `espoImage.show` → modal `views/wysiwyg/modals/insert-image`, whose **upload** path runs through `insertImagesOrCallback` → the `onImageUpload` callback above. (The modal's **URL** path inserts a plain remote `<img>` instead — not what we want.)
Verify before relying on it:
```
podman exec espocrm_ctr sh -lc "grep -n 'setupToolbar\|espoLink\|espoImage\|table' /var/www/html/client/src/views/preferences/fields/signature.js"
podman exec espocrm_ctr sh -lc "grep -n 'onImageUpload\|uploadInlineAttachment\|entryPoint=attachment' /var/www/html/client/src/views/fields/wysiwyg.js"
```
You should see the reduced toolbar with `['table', ['espoLink']]` and the `onImageUpload`→attachment path. If the structure differs in this build, adjust the toolbar-patch below to match the real group names.
### Steps
1. **Confirm container.** `podman ps` → identify the web container (expected `espocrm_ctr`).
2. **Create the custom signature field view** on the persisted mount:
`/var/www/html/client/custom/src/views/preferences/fields/signature.js`
```js
define('custom:views/preferences/fields/signature',
['views/preferences/fields/signature'], (SignatureFieldView) => {
return class extends SignatureFieldView {
setupToolbar() {
// Build the reduced signature toolbar first …
super.setupToolbar();
// … then re-add the image button next to the link button.
this.toolbar = (this.toolbar || []).map(group => {
if (Array.isArray(group) && group[0] === 'table') {
const buttons = group[1] || [];
if (!buttons.includes('espoImage')) {
return ['table', [...buttons, 'espoImage']];
}
}
return group;
});
}
};
});
```
Create the directory if needed:
```
podman exec espocrm_ctr sh -lc "mkdir -p /var/www/html/client/custom/src/views/preferences/fields"
```
> If the `grep` in the verify step shows no group whose first element is `'table'`, fall back to simply appending a new group instead of the `.map(...)`: `this.toolbar.push(['insert', ['espoImage']]);` (place it before the final `['misc', …]` group if you want it left of code-view/fullscreen).
3. **Point the signature field at the custom view** via an entityDefs override. Merge into (create if absent):
`/var/www/html/custom/Espo/Custom/Resources/metadata/entityDefs/Preferences.json`
```json
{
"fields": {
"signature": {
"view": "custom:views/preferences/fields/signature"
}
}
}
```
**MERGE** — if the file already exists, preserve all other keys and only add `fields.signature.view`. Do not drop the field's `type` (it stays `wysiwyg`; metadata is merged on top of core). Produce valid JSON.
4. **Fix ownership** (as root in the container):
```
podman exec espocrm_ctr chown -R www-data:www-data /var/www/html/client/custom /var/www/html/custom/Espo/Custom/Resources/metadata
```
5. **Clear cache / rebuild** (as the web user):
```
podman exec -u www-data espocrm_ctr php command.php rebuild
```
(If `command.php` is missing in this build, use `bin/command rebuild`; or Administration → Rebuild in the UI as admin.)
6. **Verify (hard reload Ctrl+Shift+R first).** Open Benutzereinstellungen → the „E-Mail Signatur" editor. The toolbar must now show a **Bild/Image button** (picture icon) next to the link button. Click it → a „Bild einfügen" dialog opens with a **file-upload** option (and a URL field). Nothing else in EspoCRM should have changed.
### Rollback
1. Delete `/var/www/html/client/custom/src/views/preferences/fields/signature.js`.
2. Remove the `fields.signature.view` key from `…/metadata/entityDefs/Preferences.json` (or delete the file if it now only contains that key).
3. Rebuild (step 5) and hard-reload the browser.