TYPO3 v15 dev-main snapshot ()

This commit is contained in:
wappler committed 2026-08-10 22:31:00 +02:00
commit f9941541b7
1178 files changed
+135377

No files matched your search

@@ -0,0 +1,13 @@
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
import{LitElement as F,html as r,nothing as y}from"lit";import{property as T,state as w,customElement as D}from"lit/decorators.js";import{classMap as I}from"lit/directives/class-map.js";import{repeat as x}from"lit/directives/repeat.js";import p,{BookmarkStoreChangedEvent as z,BookmarkGroupType as S}from"@typo3/backend/bookmark/bookmark-store.js";import $ from"@typo3/backend/modal.js";import m from"@typo3/backend/notification.js";import{SeverityEnum as B}from"@typo3/backend/enum/severity.js";import{PseudoButtonLitElement as R}from"@typo3/backend/element/pseudo-button.js";import"@typo3/backend/element/spinner-element.js";import"@typo3/backend/element/icon-element.js";import a from"~labels/core.bookmarks";var g=function(k,e,t,o){var i=arguments.length,s=i<3?e:o===null?o=Object.getOwnPropertyDescriptor(e,t):o,l;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")s=Reflect.decorate(k,e,t,o);else for(var d=k.length-1;d>=0;d--)(l=k[d])&&(s=(i<3?l(s):i>3?l(e,t,s):l(e,t))||s);return i>3&&s&&Object.defineProperty(e,t,s),s};class M{constructor(){this.view="list"}}class V{constructor(e){this.bookmark=e,this.view="editBookmark"}}class E{constructor(){this.view="createGroup",this.draft={label:""}}}class L{constructor(e){this.group=e,this.view="editGroup"}}class C{constructor(){this.view="manageGroups"}}let h=class extends F{constructor(){super(...arguments),this.editId=null,this.bookmarks=[],this.groups=[],this.selectedIds=new Set,this.draggedItem=null,this.dropTarget=null,this.groupedBookmarks=new Map,this.viewState=new M,this.handleStoreUpdate=()=>{this.syncFromStore()},this.handleBookmarkBulkDelete=()=>{const e=Array.from(this.selectedIds),t=$.confirm(a.get("confirmDeleteMultiple.title"),a.get("confirmDeleteMultiple.message",[e.length]),B.notice,[{text:a.get("action.cancel"),btnClass:"btn-default",name:"cancel",trigger:()=>t.hideModal()},{text:a.get("action.delete"),btnClass:"btn-primary",name:"delete",trigger:async()=>{await p.deleteMultiple(e)?(m.success(a.get("success.deletedMultiple.title"),a.get("success.deletedMultiple.message",[e.length])),this.selectedIds=new Set):m.error(a.get("error.deleteFailed.title"),a.get("error.deleteFailed.message")),t.hideModal()}}])},this.handleDragOver=e=>{e.preventDefault(),e.dataTransfer&&(e.dataTransfer.dropEffect="move")},this.handleItemDragLeave=e=>{const t=e.relatedTarget;t&&e.currentTarget.contains(t)||(this.dropTarget=null)},this.handleDragEnd=()=>{this.draggedItem=null,this.dropTarget=null}}connectedCallback(){super.connectedCallback(),document.addEventListener(z,this.handleStoreUpdate),this.initFromStore()}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener(z,this.handleStoreUpdate)}createRenderRoot(){return this}render(){let e;return this.viewState instanceof V?e=this.renderBookmarkEditView(this.viewState):this.viewState instanceof C?e=this.renderGroupListView():this.viewState instanceof E?e=this.renderGroupCreateView(this.viewState):this.viewState instanceof L?e=this.renderGroupEditView(this.viewState):e=this.renderBookmarkListView(),r`<div class=bookmark-manager><div class=bookmark-manager-toolbar>${e.toolbar}</div><div class=bookmark-manager-content>${e.content}</div></div>`}async initFromStore(){if(await this.syncFromStore(),this.editId!==null){const e=this.bookmarks.find(t=>t.id===this.editId);e&&this.navigateToBookmarkEditView(e)}}navigateToBookmarkListView(){this.viewState=new M}navigateToBookmarkEditView(e){this.viewState=new V(e)}navigateToGroupListView(){this.viewState=new C}navigateToGroupCreateView(){this.viewState=new E}navigateToGroupEditView(e){this.viewState=new L(e)}renderBookmarkListView(){const e=this.groupedBookmarks,t=this.selectedIds.size>0,o=this.bookmarks.length>0,i=this.selectedIds.size===this.bookmarks.length&&this.bookmarks.length>0,s=this.helperGetGroupSections(this.getSelectableGroups()),l=r`<div class=bookmark-manager-toolbar-start><div class=form-slim><div class=form-group><div class="form-check form-check-type-toggle mb-0"><input type=checkbox class=form-check-input id=selectAll .checked=${i} @change=${n=>{this.selectedIds=n.target.checked?new Set(this.bookmarks.map(b=>b.id)):new Set}}> <label class=form-check-label for=selectAll>${i?a.get("manager.deselectAll"):a.get("manager.selectAll")}</label></div></div>${t?r`<div class="form-group dropdown"><button class="btn btn-sm btn-default dropdown-toggle" type=button data-bs-toggle=dropdown aria-expanded=false><typo3-backend-icon identifier=actions-bookmarks size=small></typo3-backend-icon>${a.get("manager.moveToGroup")}</button><ul class=dropdown-menu>${s.map((n,b)=>r`${b>0?r`<li><hr class=dropdown-divider></li>`:y}<li><div class=dropdown-header>${n.label}</div></li>${n.groups.map(f=>r`<li><button class=dropdown-item type=button @click=${()=>this.handleBookmarkBulkMove(f.id)}>${f.label}</button></li>`)}`)}</ul></div><div class=form-group><button class="btn btn-sm btn-default" type=button @click=${this.handleBookmarkBulkDelete}><typo3-backend-icon ident Line truncated
@@ -0,0 +1,13 @@
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
import n from"@typo3/core/ajax/ajax-request.js";import i from"~labels/core.bookmarks";import g from"~labels/core.mod_web_list";import F from"@typo3/backend/modal.js";import p from"@typo3/backend/notification.js";import{SeverityEnum as _}from"@typo3/backend/enum/severity.js";import{BroadcastMessage as B}from"@typo3/backend/broadcast-message.js";import E from"@typo3/backend/broadcast-service.js";const h="typo3:bookmark-store:changed";var k;(function(c){c.SYSTEM="system",c.GLOBAL="global",c.USER="user"})(k||(k={}));class f{constructor(){this.bookmarks=new Map,this.groups=[],this.isLoaded=!1,this.loadPromise=null,document.addEventListener("typo3:bookmark:broadcast",e=>this.handleBroadcast(e))}getBookmarkKey(e,r){return`${e}::${r}`}async isBookmarked(e){return await this.getBookmark(e)!==null}async getBookmark(e){await this.ready();for(const r of this.bookmarks.values())if(this.getBookmarkKey(r.route,r.arguments)===e)return r;return null}async getBookmarks(){return await this.ready(),[...this.bookmarks.values()]}async getGroups(){return await this.ready(),[...this.groups]}async getGroupedBookmarks(e){let r=await this.getBookmarks();e?.accessibleOnly&&(r=r.filter(a=>a.accessible)),e?.groupId!==void 0&&(r=r.filter(a=>a.groupId===e.groupId)),e?.limit!==void 0&&e.limit>0&&r.length>e.limit&&(r=r.slice(0,e.limit));const o=new Map,t=new Map,s=new Map;this.groups.forEach(a=>{t.set(a.id,a.priority),s.set(a.id,a.sorting)});const b=[...new Set(r.map(a=>a.groupId))].sort((a,l)=>{const d=t.get(a)??Number.MAX_SAFE_INTEGER,y=t.get(l)??Number.MAX_SAFE_INTEGER,m=d-y;if(m!==0)return m;const w=s.get(a)??Number.MAX_SAFE_INTEGER,v=s.get(l)??Number.MAX_SAFE_INTEGER;return w-v});for(const a of b){const l=r.filter(d=>d.groupId===a);l.length>0&&o.set(a,l)}return o}initialize(e,r){this.isLoaded||this.load({bookmarks:e,groups:r})}async create(e,r,o){try{const s=await(await new n(TYPO3.settings.ajaxUrls.bookmark_create).post({routeIdentifier:e,arguments:r,displayName:o||""})).resolve();return s.success&&s.bookmark&&(this.bookmarks.set(s.bookmark.id,s.bookmark),this.notifyChanged()),s}catch(t){return console.error("Failed to create bookmark:",t),{success:!1,error:i.get("error.createFailed.message")}}}async update(e,r,o){try{const s=await(await new n(TYPO3.settings.ajaxUrls.bookmark_update).post({bookmarkId:e,bookmarkTitle:r,bookmarkGroup:o})).resolve();return s.success&&s.bookmark&&(this.bookmarks.set(s.bookmark.id,s.bookmark),this.notifyChanged()),s}catch(t){return console.error("Failed to update bookmark:",t),{success:!1,error:i.get("error.updateFailed.message")}}}requestDelete(e){if(!this.bookmarks.get(e))return;const o=F.confirm(i.get("delete"),i.get("confirmDelete.title"),_.warning,[{text:g.get("button.cancel"),btnClass:"btn-default",name:"cancel",trigger:()=>o.hideModal()},{text:g.get("button.delete"),btnClass:"btn-danger",name:"delete",trigger:async()=>{o.hideModal();const t=await this.delete(e);t.success?p.success(i.get("success.deleted.title"),i.get("success.deleted.message")):p.error(i.get("error.deleteFailed.title"),t.error||i.get("error.deleteFailed.message"))}}])}async delete(e){try{const o=await(await new n(TYPO3.settings.ajaxUrls.bookmark_delete).post({bookmarkId:e})).resolve();return o.success&&(this.bookmarks.delete(e),this.notifyChanged()),o}catch(r){return console.error("Failed to delete bookmark:",r),{success:!1,error:i.get("error.deleteFailed.message")}}}async reorder(e){try{const o=await(await new n(TYPO3.settings.ajaxUrls.bookmark_reorder).post({bookmarkIds:e})).resolve();if(o.success&&o.bookmarks){this.bookmarks.clear();for(const t of o.bookmarks)this.bookmarks.set(t.id,t);return this.notifyChanged(),!0}return!1}catch(r){return console.error("Failed to reorder bookmarks:",r),!1}}async deleteMultiple(e){try{if((await(await new n(TYPO3.settings.ajaxUrls.bookmark_delete_multiple).post({bookmarkIds:e})).resolve()).success){for(const t of e)this.bookmarks.delete(t);return this.notifyChanged(),!0}return!1}catch(r){return console.error("Failed to delete multiple bookmarks:",r),!1}}async move(e,r){try{if((await(await new n(TYPO3.settings.ajaxUrls.bookmark_move).post({bookmarkIds:e,groupId:r})).resolve()).success){for(const s of e){const u=this.bookmarks.get(s);u&&this.bookmarks.set(s,{...u,groupId:r})}return this.notifyChanged(),!0}return!1}catch(o){return console.error("Failed to move bookmarks:",o),!1}}async refresh(){this.isLoaded=!1,this.loadPromise=null,await this.fetchAll()}async createGroup(e){try{const o=await(await new n(TYPO3.settings.ajaxUrls.bookmark_group_create).post({label:e})).resolve();return o.success&&o.group&&(this.groups.push(o.group),this.notifyChanged()),o}catch(r){return console.error("Failed to create group:",r),{success:!1,error:i.get("error.groupCreateFailed.message")}}}async updateGroup(e,r){try{const t=await(await new n(TYPO3.settings.ajaxUrls.bookmark_group_update).post({uuid:e,label:r})).resolve();return t.success&&t.groups&&(this.groups=t.groups,this.notifyChanged()),t}catch(o){return consoleLine truncated
@@ -0,0 +1,13 @@
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
import{html as m}from"lit";import{property as k,state as p,customElement as f}from"lit/decorators.js";import s from"~labels/core.bookmarks";import{PseudoButtonLitElement as y}from"@typo3/backend/element/pseudo-button.js";import n,{BookmarkStoreChangedEvent as u}from"@typo3/backend/bookmark/bookmark-store.js";import b from"@typo3/backend/notification.js";import"@typo3/backend/element/icon-element.js";import"@typo3/backend/element/spinner-element.js";var r=function(c,e,o,a){var d=arguments.length,i=d<3?e:a===null?a=Object.getOwnPropertyDescriptor(e,o):a,l;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")i=Reflect.decorate(c,e,o,a);else for(var h=c.length-1;h>=0;h--)(l=c[h])&&(i=(d<3?l(i):d>3?l(e,o,i):l(e,o))||i);return d>3&&i&&Object.defineProperty(e,o,i),i};let t=class extends y{constructor(){super(...arguments),this.route="",this.arguments="",this.displayName="",this.hideLabelText=!1,this.isBookmarked=!1,this.isProcessing=!1,this.handleStoreUpdate=async()=>{await this.checkIfBookmarked(),this.updateState()}}get bookmarkKey(){return n.getBookmarkKey(this.route,this.arguments)}connectedCallback(){super.connectedCallback(),document.addEventListener(u,this.handleStoreUpdate),this.setup()}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener(u,this.handleStoreUpdate)}createRenderRoot(){return this}render(){const e=this.isBookmarked?s.get("action.remove"):s.get("action.create"),o=this.hideLabelText?m`<span class=visually-hidden>${e}</span>`:m`${e}`;if(this.isProcessing)return m`<typo3-backend-spinner size=small></typo3-backend-spinner>${o}`;const a=this.isBookmarked?"actions-bookmark-remove":"actions-bookmark-add";return m`<typo3-backend-icon identifier=${a} size=small></typo3-backend-icon>${o}`}async buttonActivated(){if(!this.isProcessing){this.isProcessing=!0,this.updateState();try{if(this.isBookmarked){const e=await n.getBookmark(this.bookmarkKey);e&&n.requestDelete(e.id)}else{const e=await n.create(this.route,this.arguments,this.displayName);e.success?b.success(s.get("success.created.title"),s.get("success.created.message")):b.error(s.get("error.createFailed.title"),e.error||s.get("error.createFailed.message"))}}finally{this.isProcessing=!1,await this.checkIfBookmarked(),this.updateState()}}}async setup(){await this.checkIfBookmarked(),this.updateState()}async checkIfBookmarked(){this.isBookmarked=await n.isBookmarked(this.bookmarkKey)}updateState(){this.isProcessing?(this.setAttribute("aria-disabled","true"),this.tabIndex=-1):(this.removeAttribute("aria-disabled"),this.tabIndex=0),this.setAttribute("aria-pressed",this.isBookmarked?"true":"false"),this.title=this.isBookmarked?s.get("action.remove"):s.get("action.create")}};r([k({type:String})],t.prototype,"route",void 0),r([k({type:String})],t.prototype,"arguments",void 0),r([k({type:String,attribute:"display-name"})],t.prototype,"displayName",void 0),r([k({type:Boolean,attribute:"hide-label-text"})],t.prototype,"hideLabelText",void 0),r([p()],t.prototype,"isBookmarked",void 0),r([p()],t.prototype,"isProcessing",void 0),t=r([f("typo3-backend-bookmark-button")],t);export{t as BookmarkButtonElement};
@@ -0,0 +1,13 @@
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
import{LitElement as b,html as i,nothing as u}from"lit";import{state as h,customElement as f}from"lit/decorators.js";import{repeat as k}from"lit/directives/repeat.js";import c,{BookmarkStoreChangedEvent as g}from"@typo3/backend/bookmark/bookmark-store.js";import"@typo3/backend/element/icon-element.js";import"@typo3/backend/bookmark/bookmark-manager.js";import l from"~labels/core.bookmarks";var m=function(p,e,o,n){var a=arguments.length,t=a<3?e:n===null?n=Object.getOwnPropertyDescriptor(e,o):n,s;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")t=Reflect.decorate(p,e,o,n);else for(var r=p.length-1;r>=0;r--)(s=p[r])&&(t=(a<3?s(t):a>3?s(e,o,t):s(e,o))||t);return a>3&&t&&Object.defineProperty(e,o,t),t};let d=class extends b{constructor(){super(...arguments),this.groupedBookmarks=new Map,this.groups=[],this.handleStoreUpdate=()=>{this.syncFromStore()}}connectedCallback(){super.connectedCallback(),document.addEventListener(g,this.handleStoreUpdate),this.syncFromStore()}disconnectedCallback(){super.disconnectedCallback(),document.removeEventListener(g,this.handleStoreUpdate)}createRenderRoot(){return this}render(){return i`<p class=dropdown-headline>${l.get("title")}</p>${this.renderContent()}<hr class=dropdown-divider aria-hidden=true><typo3-backend-bookmark-manager-button class=dropdown-item><span class=dropdown-item-columns> <span class="dropdown-item-column dropdown-item-column-icon" aria-hidden=true><typo3-backend-icon identifier=actions-cog size=small></typo3-backend-icon> </span> <span class="dropdown-item-column dropdown-item-column-title">${l.get("manage")} </span> </span></typo3-backend-bookmark-manager-button>`}async syncFromStore(){this.groupedBookmarks=await c.getGroupedBookmarks({accessibleOnly:!0}),this.groups=await c.getGroups()}renderContent(){if(this.groupedBookmarks.size===0)return i`<p class=dropdown-item-text>${l.get("description")}</p>`;let e=!0;return i`${k(Array.from(this.groupedBookmarks.entries()),([o])=>o,([o,n])=>{const a=this.renderGroup(o,n,e);return e=!1,a})}`}renderGroup(e,o,n){const t=this.groups.find(r=>r.id===e)?.label,s=t||this.groups.length>1;return i`${n?u:i`<hr class=dropdown-divider aria-hidden=true>`} ${s?i`<p class=dropdown-header id=bookmark-group-${e}>${t||l.get("notGrouped")}</p>`:u}<ul class=dropdown-list data-bookmarkgroup=${e}>${k(o,r=>r.id,r=>this.renderBookmarkItem(r,e))}</ul>`}renderBookmarkItem(e,o){return i`<li class=t3js-topbar-bookmark data-bookmarkid=${e.id} data-bookmarkgroup=${o}><button type=button class=dropdown-item title=${e.title} @click=${()=>this.handleNavigate(e)}><span class=dropdown-item-columns> <span class="dropdown-item-column dropdown-item-column-icon" aria-hidden=true><typo3-backend-icon identifier=${e.iconIdentifier} overlay=${e.iconOverlayIdentifier} size=small></typo3-backend-icon> </span> <span class="dropdown-item-column dropdown-item-column-title">${e.title} </span> </span></button></li>`}handleNavigate(e){c.navigate(e)}};m([h()],d.prototype,"groupedBookmarks",void 0),m([h()],d.prototype,"groups",void 0),d=m([f("typo3-backend-bookmark-menu")],d);export{d as BookmarkMenuElement};