From 103288b971ce6fe27a270e88bab4c31557b1d0b5 Mon Sep 17 00:00:00 2001
From: Georg Ringer <georg.ringer@gmail.com>
Date: Sat, 8 Jun 2024 09:58:49 +0200
Subject: [PATCH] [TASK] Replace invalid icon with working example

The backend layout wizard now uses a working example by using an
existing icon.

Resolves: #91910
Releases: main, 12.4
Change-Id: If6df3bd73d1ff6dc1a7a3e71cadf2e89b1a18bd5
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/84529
Tested-by: Benni Mack <benni@typo3.org>
Tested-by: core-ci <typo3@b13.com>
Reviewed-by: Benni Mack <benni@typo3.org>
Reviewed-by: Nikita Hovratov <nikita.h@live.de>
Reviewed-by: Georg Ringer <georg.ringer@gmail.com>
Tested-by: Garvin Hicking <gh@faktor-e.de>
Reviewed-by: Garvin Hicking <gh@faktor-e.de>
Tested-by: Georg Ringer <georg.ringer@gmail.com>
---
 Build/Sources/TypeScript/backend/grid-editor.ts                 | 2 +-
 .../View/BackendLayout/PageTsBackendLayoutDataProvider.php      | 2 +-
 typo3/sysext/backend/Resources/Public/JavaScript/grid-editor.js | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/Build/Sources/TypeScript/backend/grid-editor.ts b/Build/Sources/TypeScript/backend/grid-editor.ts
index dfae9dd4955f..0214eaa608f4 100644
--- a/Build/Sources/TypeScript/backend/grid-editor.ts
+++ b/Build/Sources/TypeScript/backend/grid-editor.ts
@@ -436,7 +436,7 @@ export class GridEditor extends LitElement {
     const content = 'mod.web_layout.BackendLayouts {\n' +
       '  exampleKey {\n' +
       '    title = Example\n' +
-      '    icon = EXT:example_extension/Resources/Public/Images/BackendLayouts/default.gif\n' +
+      '    icon = content-container-columns-2\n' +
       '    config {\n' +
       config.replace(new RegExp('\\t', 'g'), '  ') +
       '    }\n' +
diff --git a/typo3/sysext/backend/Classes/View/BackendLayout/PageTsBackendLayoutDataProvider.php b/typo3/sysext/backend/Classes/View/BackendLayout/PageTsBackendLayoutDataProvider.php
index 390443b81bfb..b3dadad118a0 100644
--- a/typo3/sysext/backend/Classes/View/BackendLayout/PageTsBackendLayoutDataProvider.php
+++ b/typo3/sysext/backend/Classes/View/BackendLayout/PageTsBackendLayoutDataProvider.php
@@ -55,7 +55,7 @@ use TYPO3\CMS\Core\Utility\ArrayUtility;
  * 						}
  * 					}
  * 				}
- * 				icon = EXT:example_extension/Resources/Public/Images/BackendLayouts/default.gif
+ * 				icon = content-container-columns-2
  * 			}
  * 		}
  * 	}
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/grid-editor.js b/typo3/sysext/backend/Resources/Public/JavaScript/grid-editor.js
index 33c48ab6f805..6ad70be46977 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/grid-editor.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/grid-editor.js
@@ -118,4 +118,4 @@ var GridEditor_1,__decorate=function(t,e,o,r){var i,n=arguments.length,a=n<3?e:n
         ${ref(this.codeMirrorRef)}>
         <textarea class="t3js-tsconfig-preview-area form-control" ${ref(this.previewAreaRef)}></textarea>
       </typo3-t3editor-codemirror>
-    `}getNewCell(){return structuredClone(this.defaultCell)}writeConfig(t){this.field.value=t;const e=t.split("\n");let o="";for(const t of e)t&&(o+="\t\t\t"+t+"\n");const r="mod.web_layout.BackendLayouts {\n  exampleKey {\n    title = Example\n    icon = EXT:example_extension/Resources/Public/Images/BackendLayouts/default.gif\n    config {\n"+o.replace(new RegExp("\\t","g"),"  ")+"    }\n  }\n}\n";this.previewAreaRef.value.value=r;const i=this.codeMirrorRef.value;i&&i.editorView&&i.editorView.dispatch({changes:{from:0,to:i.editorView.viewState.state.doc.length,insert:r}})}addRowTop(){const t=[];for(let e=0;e<this.colCount;e++){const o=this.getNewCell();o.name=e+"x"+this.data.length,t[e]=o}this.data.unshift(t),this.rowCount++}addRowBottom(){const t=[];for(let e=0;e<this.colCount;e++){const o=this.getNewCell();o.name=e+"x"+this.data.length,t[e]=o}this.data.push(t),this.rowCount++}removeRowTop(){if(this.rowCount<=1)return!1;const t=[];for(let e=1;e<this.rowCount;e++)t.push(this.data[e]);for(let t=0;t<this.colCount;t++)1===this.data[0][t].spanned&&this.findUpperCellWidthRowspanAndDecreaseByOne(t,0);return this.data=t,this.rowCount--,!0}removeRowBottom(){if(this.rowCount<=1)return!1;const t=[];for(let e=0;e<this.rowCount-1;e++)t.push(this.data[e]);for(let t=0;t<this.colCount;t++)1===this.data[this.rowCount-1][t].spanned&&this.findUpperCellWidthRowspanAndDecreaseByOne(t,this.rowCount-1);return this.data=t,this.rowCount--,!0}findUpperCellWidthRowspanAndDecreaseByOne(t,e){const o=this.getCell(t,e-1);return!!o&&(1===o.spanned?this.findUpperCellWidthRowspanAndDecreaseByOne(t,e-1):o.rowspan>1&&this.removeRowspan(t,e-1),!0)}removeColumn(){if(this.colCount<=1)return!1;const t=[];for(let e=0;e<this.rowCount;e++){const o=[];for(let t=0;t<this.colCount-1;t++)o.push(this.data[e][t]);1===this.data[e][this.colCount-1].spanned&&this.findLeftCellWidthColspanAndDecreaseByOne(this.colCount-1,e),t.push(o)}return this.data=t,this.colCount--,!0}findLeftCellWidthColspanAndDecreaseByOne(t,e){const o=this.getCell(t-1,e);return!!o&&(1===o.spanned?this.findLeftCellWidthColspanAndDecreaseByOne(t-1,e):o.colspan>1&&this.removeColspan(t-1,e),!0)}addColumn(){for(let t=0;t<this.rowCount;t++){const e=this.getNewCell();e.name=this.colCount+"x"+t,this.data[t].push(e)}this.colCount++}setName(t,e,o){const r=this.getCell(e,o);return!!r&&(r.name=GridEditor_1.stripMarkup(t),!0)}setColumn(t,e,o){const r=this.getCell(e,o);return!!r&&(r.column=parseInt(t.toString(),10),!0)}showOptions(t,e){const o=this.getCell(t,e);if(!o)return!1;let r;r=0===o.column?0:o.column?parseInt(o.column.toString(),10):"";const i=document.createElement("div"),n=document.createElement("div");n.classList.add("form-group");const a=document.createElement("label"),s=document.createElement("input"),l=n.cloneNode(!0),d=a.cloneNode(!0);d.innerText=TYPO3.lang.grid_nameHelp;const c=s.cloneNode(!0);c.type="text",c.classList.add("t3js-grideditor-field-name","form-control"),c.name="name",c.value=GridEditor_1.stripMarkup(o.name)||"",l.append(d,c);const p=n.cloneNode(!0),h=a.cloneNode(!0);h.innerText=TYPO3.lang.grid_columnHelp;const u=s.cloneNode(!0);u.type="text",u.classList.add("t3js-grideditor-field-colpos","form-control"),u.name="column",u.value=r.toString(),p.append(h,u),i.append(l,p);const g=Modal.show(TYPO3.lang.grid_windowTitle,i,SeverityEnum.notice,[{active:!0,btnClass:"btn-default",name:"cancel",text:TYPO3.lang["button.cancel"]||"Cancel"},{btnClass:"btn-primary",name:"ok",text:TYPO3.lang["button.ok"]||"OK"}]);return g.userData.col=t,g.userData.row=e,g.addEventListener("button.clicked",this.modalButtonClickHandler),!0}getCell(t,e){return!(t>this.colCount-1)&&(!(e>this.rowCount-1)&&(this.data.length>e-1&&this.data[e].length>t-1?this.data[e][t]:null))}cellCanSpanRight(t,e){if(t===this.colCount-1)return!1;const o=this.getCell(t,e);if(!o)return!1;let r;if(o.rowspan>1){for(let i=e;i<e+o.rowspan;i++)if(r=this.getCell(t+o.colspan,i),!r||1===r.spanned||r.colspan>1||r.rowspan>1)return!1}else if(r=this.getCell(t+o.colspan,e),!r||1===o.spanned||1===r.spanned||r.colspan>1||r.rowspan>1)return!1;return!0}cellCanSpanDown(t,e){if(e===this.rowCount-1)return!1;const o=this.getCell(t,e);if(!o)return!1;let r;if(o.colspan>1){for(let i=t;i<t+o.colspan;i++)if(r=this.getCell(i,e+o.rowspan),!r||1===r.spanned||r.colspan>1||r.rowspan>1)return!1}else if(r=this.getCell(t,e+o.rowspan),!r||1===o.spanned||1===r.spanned||r.colspan>1||r.rowspan>1)return!1;return!0}cellCanShrinkLeft(t,e){return this.data[e][t].colspan>1}cellCanShrinkUp(t,e){return this.data[e][t].rowspan>1}addColspan(t,e){const o=this.getCell(t,e);if(!o||!this.cellCanSpanRight(t,e))return!1;for(let r=e;r<e+o.rowspan;r++)this.data[r][t+o.colspan].spanned=1;return o.colspan+=1,!0}addRowspan(t,e){const o=this.getCell(t,e);if(!o||!this.cellCanSpanDown(t,e))return!1;for(let r=t;r<t+o.colspan;r++)this.data[e+o.rowspan][r].spanned=1;return o.rowspan+=1,!0}removeColspan(t,e){const o=this.getCell(t,e);if(!o||!this.cellCanShrinkLeft(t,e))return!1;o.colspan-=1;for(let r=e;r<e+o.rowspan;r++)this.data[r][t+o.colspan].spanned=0;return!0}removeRowspan(t,e){const o=this.getCell(t,e);if(!o||!this.cellCanShrinkUp(t,e))return!1;o.rowspan-=1;for(let r=t;r<t+o.colspan;r++)this.data[e+o.rowspan][r].spanned=0;return!0}export2LayoutRecord(){let t="backend_layout {\n\tcolCount = "+this.colCount+"\n\trowCount = "+this.rowCount+"\n\trows {\n";for(let e=0;e<this.rowCount;e++){t+="\t\t"+(e+1)+" {\n",t+="\t\t\tcolumns {\n";let o=0;for(let r=0;r<this.colCount;r++){const i=this.getCell(r,e);if(i&&!i.spanned){const n=GridEditor_1.stripMarkup(i.name)||"";o++,t+="\t\t\t\t"+o+" {\n",t+="\t\t\t\t\tname = "+(n||r+"x"+e)+"\n",i.colspan>1&&(t+="\t\t\t\t\tcolspan = "+i.colspan+"\n"),i.rowspan>1&&(t+="\t\t\t\t\trowspan = "+i.rowspan+"\n"),"number"==typeof i.column&&(t+="\t\t\t\t\tcolPos = "+i.column+"\n"),t+="\t\t\t\t}\n"}}t+="\t\t\t}\n",t+="\t\t}\n"}return t+="\t}\n}\n",t}addVisibilityObserver(t){null===t.offsetParent&&new IntersectionObserver((t=>{t.forEach((t=>{const e=this.codeMirrorRef.value;t.intersectionRatio>0&&e&&e.requestUpdate()}))})).observe(t)}};__decorate([property({type:Number})],GridEditor.prototype,"colCount",void 0),__decorate([property({type:Number})],GridEditor.prototype,"rowCount",void 0),__decorate([property({type:Boolean})],GridEditor.prototype,"readOnly",void 0),__decorate([property({type:String})],GridEditor.prototype,"fieldName",void 0),__decorate([property({type:Array})],GridEditor.prototype,"data",void 0),__decorate([property({type:Object})],GridEditor.prototype,"codeMirrorConfig",void 0),GridEditor=GridEditor_1=__decorate([customElement("typo3-backend-grid-editor")],GridEditor);export{GridEditor};
\ No newline at end of file
+    `}getNewCell(){return structuredClone(this.defaultCell)}writeConfig(t){this.field.value=t;const e=t.split("\n");let o="";for(const t of e)t&&(o+="\t\t\t"+t+"\n");const r="mod.web_layout.BackendLayouts {\n  exampleKey {\n    title = Example\n    icon = content-container-columns-2\n    config {\n"+o.replace(new RegExp("\\t","g"),"  ")+"    }\n  }\n}\n";this.previewAreaRef.value.value=r;const i=this.codeMirrorRef.value;i&&i.editorView&&i.editorView.dispatch({changes:{from:0,to:i.editorView.viewState.state.doc.length,insert:r}})}addRowTop(){const t=[];for(let e=0;e<this.colCount;e++){const o=this.getNewCell();o.name=e+"x"+this.data.length,t[e]=o}this.data.unshift(t),this.rowCount++}addRowBottom(){const t=[];for(let e=0;e<this.colCount;e++){const o=this.getNewCell();o.name=e+"x"+this.data.length,t[e]=o}this.data.push(t),this.rowCount++}removeRowTop(){if(this.rowCount<=1)return!1;const t=[];for(let e=1;e<this.rowCount;e++)t.push(this.data[e]);for(let t=0;t<this.colCount;t++)1===this.data[0][t].spanned&&this.findUpperCellWidthRowspanAndDecreaseByOne(t,0);return this.data=t,this.rowCount--,!0}removeRowBottom(){if(this.rowCount<=1)return!1;const t=[];for(let e=0;e<this.rowCount-1;e++)t.push(this.data[e]);for(let t=0;t<this.colCount;t++)1===this.data[this.rowCount-1][t].spanned&&this.findUpperCellWidthRowspanAndDecreaseByOne(t,this.rowCount-1);return this.data=t,this.rowCount--,!0}findUpperCellWidthRowspanAndDecreaseByOne(t,e){const o=this.getCell(t,e-1);return!!o&&(1===o.spanned?this.findUpperCellWidthRowspanAndDecreaseByOne(t,e-1):o.rowspan>1&&this.removeRowspan(t,e-1),!0)}removeColumn(){if(this.colCount<=1)return!1;const t=[];for(let e=0;e<this.rowCount;e++){const o=[];for(let t=0;t<this.colCount-1;t++)o.push(this.data[e][t]);1===this.data[e][this.colCount-1].spanned&&this.findLeftCellWidthColspanAndDecreaseByOne(this.colCount-1,e),t.push(o)}return this.data=t,this.colCount--,!0}findLeftCellWidthColspanAndDecreaseByOne(t,e){const o=this.getCell(t-1,e);return!!o&&(1===o.spanned?this.findLeftCellWidthColspanAndDecreaseByOne(t-1,e):o.colspan>1&&this.removeColspan(t-1,e),!0)}addColumn(){for(let t=0;t<this.rowCount;t++){const e=this.getNewCell();e.name=this.colCount+"x"+t,this.data[t].push(e)}this.colCount++}setName(t,e,o){const r=this.getCell(e,o);return!!r&&(r.name=GridEditor_1.stripMarkup(t),!0)}setColumn(t,e,o){const r=this.getCell(e,o);return!!r&&(r.column=parseInt(t.toString(),10),!0)}showOptions(t,e){const o=this.getCell(t,e);if(!o)return!1;let r;r=0===o.column?0:o.column?parseInt(o.column.toString(),10):"";const i=document.createElement("div"),n=document.createElement("div");n.classList.add("form-group");const a=document.createElement("label"),s=document.createElement("input"),l=n.cloneNode(!0),d=a.cloneNode(!0);d.innerText=TYPO3.lang.grid_nameHelp;const c=s.cloneNode(!0);c.type="text",c.classList.add("t3js-grideditor-field-name","form-control"),c.name="name",c.value=GridEditor_1.stripMarkup(o.name)||"",l.append(d,c);const p=n.cloneNode(!0),h=a.cloneNode(!0);h.innerText=TYPO3.lang.grid_columnHelp;const u=s.cloneNode(!0);u.type="text",u.classList.add("t3js-grideditor-field-colpos","form-control"),u.name="column",u.value=r.toString(),p.append(h,u),i.append(l,p);const g=Modal.show(TYPO3.lang.grid_windowTitle,i,SeverityEnum.notice,[{active:!0,btnClass:"btn-default",name:"cancel",text:TYPO3.lang["button.cancel"]||"Cancel"},{btnClass:"btn-primary",name:"ok",text:TYPO3.lang["button.ok"]||"OK"}]);return g.userData.col=t,g.userData.row=e,g.addEventListener("button.clicked",this.modalButtonClickHandler),!0}getCell(t,e){return!(t>this.colCount-1)&&(!(e>this.rowCount-1)&&(this.data.length>e-1&&this.data[e].length>t-1?this.data[e][t]:null))}cellCanSpanRight(t,e){if(t===this.colCount-1)return!1;const o=this.getCell(t,e);if(!o)return!1;let r;if(o.rowspan>1){for(let i=e;i<e+o.rowspan;i++)if(r=this.getCell(t+o.colspan,i),!r||1===r.spanned||r.colspan>1||r.rowspan>1)return!1}else if(r=this.getCell(t+o.colspan,e),!r||1===o.spanned||1===r.spanned||r.colspan>1||r.rowspan>1)return!1;return!0}cellCanSpanDown(t,e){if(e===this.rowCount-1)return!1;const o=this.getCell(t,e);if(!o)return!1;let r;if(o.colspan>1){for(let i=t;i<t+o.colspan;i++)if(r=this.getCell(i,e+o.rowspan),!r||1===r.spanned||r.colspan>1||r.rowspan>1)return!1}else if(r=this.getCell(t,e+o.rowspan),!r||1===o.spanned||1===r.spanned||r.colspan>1||r.rowspan>1)return!1;return!0}cellCanShrinkLeft(t,e){return this.data[e][t].colspan>1}cellCanShrinkUp(t,e){return this.data[e][t].rowspan>1}addColspan(t,e){const o=this.getCell(t,e);if(!o||!this.cellCanSpanRight(t,e))return!1;for(let r=e;r<e+o.rowspan;r++)this.data[r][t+o.colspan].spanned=1;return o.colspan+=1,!0}addRowspan(t,e){const o=this.getCell(t,e);if(!o||!this.cellCanSpanDown(t,e))return!1;for(let r=t;r<t+o.colspan;r++)this.data[e+o.rowspan][r].spanned=1;return o.rowspan+=1,!0}removeColspan(t,e){const o=this.getCell(t,e);if(!o||!this.cellCanShrinkLeft(t,e))return!1;o.colspan-=1;for(let r=e;r<e+o.rowspan;r++)this.data[r][t+o.colspan].spanned=0;return!0}removeRowspan(t,e){const o=this.getCell(t,e);if(!o||!this.cellCanShrinkUp(t,e))return!1;o.rowspan-=1;for(let r=t;r<t+o.colspan;r++)this.data[e+o.rowspan][r].spanned=0;return!0}export2LayoutRecord(){let t="backend_layout {\n\tcolCount = "+this.colCount+"\n\trowCount = "+this.rowCount+"\n\trows {\n";for(let e=0;e<this.rowCount;e++){t+="\t\t"+(e+1)+" {\n",t+="\t\t\tcolumns {\n";let o=0;for(let r=0;r<this.colCount;r++){const i=this.getCell(r,e);if(i&&!i.spanned){const n=GridEditor_1.stripMarkup(i.name)||"";o++,t+="\t\t\t\t"+o+" {\n",t+="\t\t\t\t\tname = "+(n||r+"x"+e)+"\n",i.colspan>1&&(t+="\t\t\t\t\tcolspan = "+i.colspan+"\n"),i.rowspan>1&&(t+="\t\t\t\t\trowspan = "+i.rowspan+"\n"),"number"==typeof i.column&&(t+="\t\t\t\t\tcolPos = "+i.column+"\n"),t+="\t\t\t\t}\n"}}t+="\t\t\t}\n",t+="\t\t}\n"}return t+="\t}\n}\n",t}addVisibilityObserver(t){null===t.offsetParent&&new IntersectionObserver((t=>{t.forEach((t=>{const e=this.codeMirrorRef.value;t.intersectionRatio>0&&e&&e.requestUpdate()}))})).observe(t)}};__decorate([property({type:Number})],GridEditor.prototype,"colCount",void 0),__decorate([property({type:Number})],GridEditor.prototype,"rowCount",void 0),__decorate([property({type:Boolean})],GridEditor.prototype,"readOnly",void 0),__decorate([property({type:String})],GridEditor.prototype,"fieldName",void 0),__decorate([property({type:Array})],GridEditor.prototype,"data",void 0),__decorate([property({type:Object})],GridEditor.prototype,"codeMirrorConfig",void 0),GridEditor=GridEditor_1=__decorate([customElement("typo3-backend-grid-editor")],GridEditor);export{GridEditor};
\ No newline at end of file
-- 
GitLab