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>
106 lines
6.0 KiB
Markdown
106 lines
6.0 KiB
Markdown
### 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.
|