/* * 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 console.error("Failed to update group:",o),{success:!1,error:i.get("error.groupUpdateFailed.message")}}}async deleteGroup(e){try{const o=await(await new n(TYPO3.settings.ajaxUrls.bookmark_group_delete).post({uuid:e})).resolve();return o.success&&o.groups&&(this.groups=o.groups,await this.refresh(),this.notifyChanged()),o}catch(r){return console.error("Failed to delete group:",r),{success:!1,error:i.get("error.groupDeleteFailed.message")}}}async reorderGroups(e){try{const o=await(await new n(TYPO3.settings.ajaxUrls.bookmark_group_reorder).post({uuids:e})).resolve();return o.success&&o.groups&&(this.groups=o.groups,this.notifyChanged()),o}catch(r){return console.error("Failed to reorder groups:",r),{success:!1,error:i.get("error.groupReorderFailed.message")}}}navigate(e){const r=document.querySelector("typo3-backend-module-router");if(r===null)throw new Error("Router not available.");r.setAttribute("endpoint",e.href),r.setAttribute("module",e.module)}async ready(){this.isLoaded||await this.fetchAll()}async fetchAll(){return this.isLoaded?[...this.bookmarks.values()]:(this.loadPromise||(this.loadPromise=this.doFetch()),await this.loadPromise,[...this.bookmarks.values()])}sortGroups(e){return e.sort((r,o)=>{const t=r.priority-o.priority;return t!==0?t:r.sorting-o.sorting})}handleBroadcast(e){this.load(e.detail.payload),this.notifyChanged(!1)}load(e){this.bookmarks.clear();for(const r of e.bookmarks)this.bookmarks.set(r.id,r);this.groups=this.sortGroups(e.groups),this.isLoaded=!0}notifyChanged(e=!0){const r=new CustomEvent(h);document.dispatchEvent(r);for(let o=0;o