From 43264fce3bc02876622a2ce44f448fe572ea3c47 Mon Sep 17 00:00:00 2001 From: Thomas Peterson Date: Fri, 11 Apr 2025 09:23:07 +0200 Subject: [PATCH] Fixes --- src/new/assets/controllers.json | 10 + .../assets/controllers/modal_controller.js | 69 +++ src/new/assets/lib/ckeditor.js | 16 +- src/new/assets/lib/flmngr/src/cookie.js | 158 ------- src/new/assets/lib/flmngr/src/flmngr.js | 175 ++------ .../assets/lib/flmngr/src/flmngrcommand.js | 205 --------- src/new/assets/lib/flmngr/src/index.js | 5 - .../assets/lib/flmngr/src/uploadcommand.js | 12 - src/new/assets/lib/flmngr/src/utils.js | 25 -- src/new/assets/tailwind/backend.js | 1 - src/new/composer.json | 1 + src/new/composer.lock | 235 +++++++--- src/new/config/bundles.php | 1 + src/new/importmap.php | 3 + .../Form/Extension/CKEditor5Type.php | 1 + .../Controller/Backend/FolderController.php | 406 +++++++++++++++++- .../Compiler/MediaHandlerCompilerPass.php | 10 +- .../PSC/Shop/MediaBundle/Form/MediaForm.php | 20 +- .../MediaBundle/Form/Type/TWMediaType.php | 107 +++++ .../PSC/Shop/MediaBundle/Model/MediaItem.php | 13 +- .../MediaBundle/Resources/config/services.yml | 11 +- .../views/backend/folder/cke.html.twig | 193 +++++++++ .../views/backend/folder/tw.html.twig | 157 +++++++ .../views/form/media_widget.html.twig | 4 +- .../views/form/tw_media_widget.html.twig | 54 +++ .../views/components/NewsForm.html.twig | 8 +- src/new/symfony.lock | 9 + .../templates/backend_tailwind_base.html.twig | 16 + src/new/templates/modalFrame.html.twig | 3 + 29 files changed, 1271 insertions(+), 657 deletions(-) create mode 100644 src/new/assets/controllers/modal_controller.js delete mode 100644 src/new/assets/lib/flmngr/src/cookie.js delete mode 100644 src/new/assets/lib/flmngr/src/flmngrcommand.js delete mode 100644 src/new/assets/lib/flmngr/src/index.js delete mode 100644 src/new/assets/lib/flmngr/src/uploadcommand.js delete mode 100644 src/new/assets/lib/flmngr/src/utils.js create mode 100644 src/new/src/PSC/Shop/MediaBundle/Form/Type/TWMediaType.php create mode 100644 src/new/src/PSC/Shop/MediaBundle/Resources/views/backend/folder/cke.html.twig create mode 100644 src/new/src/PSC/Shop/MediaBundle/Resources/views/backend/folder/tw.html.twig create mode 100644 src/new/src/PSC/Shop/MediaBundle/Resources/views/form/tw_media_widget.html.twig create mode 100644 src/new/templates/modalFrame.html.twig diff --git a/src/new/assets/controllers.json b/src/new/assets/controllers.json index 6d45fb171..c12f1c398 100755 --- a/src/new/assets/controllers.json +++ b/src/new/assets/controllers.json @@ -26,6 +26,16 @@ } } }, + "@symfony/ux-turbo": { + "turbo-core": { + "enabled": true, + "fetch": "eager" + }, + "mercure-turbo-stream": { + "enabled": false, + "fetch": "eager" + } + }, "@symfony/ux-vue": { "vue": { "enabled": true, diff --git a/src/new/assets/controllers/modal_controller.js b/src/new/assets/controllers/modal_controller.js new file mode 100644 index 000000000..44db5598a --- /dev/null +++ b/src/new/assets/controllers/modal_controller.js @@ -0,0 +1,69 @@ +import { Controller } from '@hotwired/stimulus'; + +export default class extends Controller { + static targets = ['dialog', 'dynamicContent']; + + observer = null; + + connect() { + if (this.hasDynamicContentTarget) { + // when the content changes, call this.open() + this.observer = new MutationObserver(() => { + const shouldOpen = this.dynamicContentTarget.innerHTML.trim().length > 0; + + if (shouldOpen && !this.dialogTarget.open) { + this.open(); + } else if (!shouldOpen && this.dialogTarget.open) { + this.close(); + } + }); + this.observer.observe(this.dynamicContentTarget, { + childList: true, + characterData: true, + subtree: true + }); + } + } + + disconnect() { + if (this.observer) { + this.observer.disconnect(); + } + if (this.dialogTarget.open) { + this.close(); + } + } + + open() { + this.dialogTarget.showModal(); + document.body.classList.add('overflow-hidden', 'blur-sm'); + } + + close() { + this.dialogTarget.close(); + document.body.classList.remove('overflow-hidden', 'blur-sm'); + } + + useMedia(e) { + let dataset = e.target.dataset; + document.getElementById(e.target.dataset.htmlId).value = e.target.dataset.id; + // Update preview + document.getElementById(e.target.dataset.htmlId + "-widget").classList.add('media-chooser--choosen'); + document.getElementById(e.target.dataset.htmlId + "__preview__title").innerHtml = this.title; + + if (e.target.dataset.thumbPath === "") { + } else { + document.getElementById(e.target.dataset.htmlId + "__preview__img").src = e.target.dataset.thumbPath; + } + + // Close modal + this.close(); + } + + clickOutside(event) { + if (event.target === this.dialogTarget) { + this.dialogTarget.close(); + } + } +} + diff --git a/src/new/assets/lib/ckeditor.js b/src/new/assets/lib/ckeditor.js index eed6a0baf..f12b10002 100644 --- a/src/new/assets/lib/ckeditor.js +++ b/src/new/assets/lib/ckeditor.js @@ -18,7 +18,7 @@ import { Paragraph, PasteFromOffice, PictureEditing, - Table, +ImageResize, Table, TableToolbar, TextTransformation, ClassicEditor @@ -45,7 +45,6 @@ EnhancedEditor.defaultConfig = { ImageCaption, ImageStyle, ImageToolbar, - ImageUpload, ImageInsertUI, Indent, Link, @@ -57,7 +56,8 @@ EnhancedEditor.defaultConfig = { Table, TableToolbar, TextTransformation, - Flmngr, +ImageResize, + Flmngr, ], toolbar: { items: [ @@ -72,15 +72,15 @@ EnhancedEditor.defaultConfig = { 'outdent', 'indent', '|', - 'uploadImage', 'blockQuote', 'insertTable', 'mediaEmbed', 'undo', 'redo', + 'undo', + 'redo', '|', - 'upload', - 'flmngr', + 'filemanager', ] }, image: { @@ -91,9 +91,9 @@ EnhancedEditor.defaultConfig = { '|', 'toggleImageCaption', 'imageTextAlternative', + 'resizeImage', '|', - 'upload', - 'flmngr', + 'filemanager', ] }, table: { diff --git a/src/new/assets/lib/flmngr/src/cookie.js b/src/new/assets/lib/flmngr/src/cookie.js deleted file mode 100644 index 61d919094..000000000 --- a/src/new/assets/lib/flmngr/src/cookie.js +++ /dev/null @@ -1,158 +0,0 @@ -;(function (factory) { - var registeredInModuleLoader = false; - if (typeof define === 'function' && define.amd) { - define(factory); - registeredInModuleLoader = true; - } - if (typeof exports === 'object') { - module.exports = factory(); - registeredInModuleLoader = true; - } - if (!registeredInModuleLoader) { - var OldCookies = window.Cookies; - var api = window.Cookies = factory(); - api.noConflict = function () { - window.Cookies = OldCookies; - return api; - }; - } -}(function () { - function extend () { - var i = 0; - var result = {}; - for (; i < arguments.length; i++) { - var attributes = arguments[ i ]; - for (var key in attributes) { - result[key] = attributes[key]; - } - } - return result; - } - - function init (converter) { - function api (key, value, attributes) { - var result; - if (typeof document === 'undefined') { - return; - } - - // Write - - if (arguments.length > 1) { - attributes = extend({ - path: '/' - }, api.defaults, attributes); - - if (typeof attributes.expires === 'number') { - var expires = new Date(); - expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5); - attributes.expires = expires; - } - - // We're using "expires" because "max-age" is not supported by IE - attributes.expires = attributes.expires ? attributes.expires.toUTCString() : ''; - - try { - result = JSON.stringify(value); - if (/^[\{\[]/.test(result)) { - value = result; - } - } catch (e) {} - - if (!converter.write) { - value = encodeURIComponent(String(value)) - .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent); - } else { - value = converter.write(value, key); - } - - key = encodeURIComponent(String(key)); - key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent); - key = key.replace(/[\(\)]/g, escape); - - var stringifiedAttributes = ''; - - for (var attributeName in attributes) { - if (!attributes[attributeName]) { - continue; - } - stringifiedAttributes += '; ' + attributeName; - if (attributes[attributeName] === true) { - continue; - } - stringifiedAttributes += '=' + attributes[attributeName]; - } - return (document.cookie = key + '=' + value + stringifiedAttributes); - } - - // Read - - if (!key) { - result = {}; - } - - // To prevent the for loop in the first place assign an empty array - // in case there are no cookies at all. Also prevents odd result when - // calling "get()" - var cookies = document.cookie ? document.cookie.split('; ') : []; - var rdecode = /(%[0-9A-Z]{2})+/g; - var i = 0; - - for (; i < cookies.length; i++) { - var parts = cookies[i].split('='); - var cookie = parts.slice(1).join('='); - - if (!this.json && cookie.charAt(0) === '"') { - cookie = cookie.slice(1, -1); - } - - try { - var name = parts[0].replace(rdecode, decodeURIComponent); - cookie = converter.read ? - converter.read(cookie, name) : converter(cookie, name) || - cookie.replace(rdecode, decodeURIComponent); - - if (this.json) { - try { - cookie = JSON.parse(cookie); - } catch (e) {} - } - - if (key === name) { - result = cookie; - break; - } - - if (!key) { - result[name] = cookie; - } - } catch (e) {} - } - - return result; - } - - api.set = api; - api.get = function (key) { - return api.call(api, key); - }; - api.getJSON = function () { - return api.apply({ - json: true - }, [].slice.call(arguments)); - }; - api.defaults = {}; - - api.remove = function (key, attributes) { - api(key, '', extend(attributes, { - expires: -1 - })); - }; - - api.withConverter = init; - - return api; - } - - return init(function () {}); -})); diff --git a/src/new/assets/lib/flmngr/src/flmngr.js b/src/new/assets/lib/flmngr/src/flmngr.js index a95d22b45..dda4e1cc2 100644 --- a/src/new/assets/lib/flmngr/src/flmngr.js +++ b/src/new/assets/lib/flmngr/src/flmngr.js @@ -1,160 +1,33 @@ import { Plugin, Notification, ButtonView } from 'ckeditor5'; -import * as Cookies from "./cookie.js"; - -//import UploadIcon from "../icons/upload.svg"; -import FlmngrCommand from "./flmngrcommand.js"; -import UploadCommand from "./uploadcommand.js"; export default class Flmngr extends Plugin { + init() { + const editor = this.editor; + // The button must be registered among the UI components of the editor + // to be displayed in the toolbar. + editor.ui.componentFactory.add( 'filemanager', () => { + // The button will be an instance of ButtonView. + const button = new ButtonView(); - listenersFlmngrIsReady = []; + button.set( { + label: 'Media', + withText: true + } ); - static get pluginName() { - return 'Flmngr'; - } - static get requires() { - return [ - Notification, - //'Image', + window.addEventListener(editor.id + '_insertImage', (event) => { + editor.execute( 'insertImage', { source: event.detail } ); + }, false); - // Default Drupal 9 CKEditor 5 will fail to attach Flmngr if these lines are not commented - // due to Link/LinkEditing plugins are not enabled until user adds Link button onto toolbar. - // So these two plugins are optional dependency for Flmngr, it can work without them. - // - // 'Link', - // 'LinkEditing', - ]; - } + button.on( 'execute', () => { + window.open( + "/apps/backend/media/list/folder/cke/" + editor.id, + "", + "width=800, height=600, resizable=yes, scrollbars=no, status=no, toolbar=no" + ); + } ); - setFlmngr(flmngr) { - const options = this.editor.config.get('flmngr') || this.editor.config.get('Flmngr') || {}; - options.integration = options["integration"] || "ckeditor5"; - options.integrationType = "flmngr"; - let flmngrInstance = flmngr.create(options); - FlmngrCommand.flmngr = flmngrInstance; - - let apiLegacy = flmngrInstance; // flmngr - // New API exists only in Flmngr v2 - let apiNew = !!apiLegacy.getNewAPI && apiLegacy.getNewAPI(); // Flmngr but without isFlmngrReady & isImgPenReady - this.editor["getFlmngr"] = (onFlmngrIsReady) => { - onFlmngrIsReady(apiNew, apiLegacy); // new way to receive Flmngr - return apiLegacy; // old way to receive Flmngr - }; - // Call all previous listeners - for (const l of this.listenersFlmngrIsReady) - l(apiNew, apiLegacy); - - window.FlmngrCKEditor5 = flmngrInstance.getNewAPI(); - } - - init() { - - this.editor["getFlmngr"] = (onFlmngrIsReady) => { - !!onFlmngrIsReady && this.listenersFlmngrIsReady.push(onFlmngrIsReady); // a new way to receive Flmngr - return null; // an old way to receive Flmngr, but it is not loaded yet, 'getFlmngr' will be overridden later to return existing values - }; - - // Include Flmngr JS lib into the document if it was not added by 3rd party code - const apiKey = this.editor.config.get('apiKey') || this.editor.config.get('flmngr.apiKey') || this.editor.config.get('Flmngr.apiKey') || 'FLMNFLMN'; - if (window.flmngr) { - // Already loaded by another instance or by using flmngr.js manually - this.setFlmngr(window.flmngr); - } else { - // We will load it and wait - if (!window.onFlmngrAndImgPenLoadedArray) - window.onFlmngrAndImgPenLoadedArray = []; - window.onFlmngrAndImgPenLoadedArray.push(() => { - this.setFlmngr(window.flmngr); - }); - - let delay = this.editor.config.get('libLoadDelay') || this.editor.config.get('flmngr.libLoadDelay') || this.editor.config.get('Flmngr.libLoadDelay'); - if (!delay || parseInt(delay) != delay) - delay = 1; - setTimeout(() => { - -// let host = "http" + (Cookies.get("N1ED_HTTPS") === "false" ? "" : "s") + "://" + (!!Cookies.get("N1ED_PREFIX") ? (Cookies.get("N1ED_PREFIX") + ".") : "") + "cloud.n1ed.com"; - -// Flmngr.includeJS(host + "/v/latest/sdk/flmngr.js?apiKey=" + apiKey); -// Flmngr.includeJS(host + "/v/latest/sdk/imgpen.js?apiKey=" + apiKey); - }, delay); - } - - /*if ( !this.editor.plugins.has( 'ImageBlockEditing' ) && !this.editor.plugins.has( 'ImageInlineEditing' ) ) { - throw new CKEditorError( 'flmngr-missing-image-plugin', this.editor ); - }*/ - - // Add the commands - this.editor.commands.add( 'upload', new UploadCommand( this.editor ) ); - this.editor.commands.add( 'flmngr', new FlmngrCommand( this.editor ) ); - - // Add UI button - const componentFactory = this.editor.ui.componentFactory; - const t = this.editor.t; - - componentFactory.add( 'upload', locale => { - const command = this.editor.commands.get( 'upload' ); - - const button = new ButtonView( locale ); - - button.set( { - label: t( 'Upload image or file' ), - withText: true, - tooltip: true - } ); - - button.bind( 'isEnabled' ).to( command ); - - button.on( 'execute', () => { - this.editor.execute( 'upload' ); - this.editor.editing.view.focus(); - } ); - - return button; - } ); - - componentFactory.add( 'flmngr', locale => { - const command = this.editor.commands.get( 'flmngr' ); - - const button = new ButtonView( locale ); - - button.set( { - label: t( 'Browse image or file' ), - withText: true, - tooltip: true - } ); - - button.bind( 'isEnabled' ).to( command ); - - button.on( 'execute', () => { - this.editor.execute( 'flmngr' ); - this.editor.editing.view.focus(); - } ); - - return button; - } ); -} - - static includeJS(urlJS) { - let scripts = document.getElementsByTagName("script"); - let alreadyExists = false; - let existingScript = null; - for (let i = 0; i < scripts.length; i++) { - let src = decodeURI(scripts[i].getAttribute("src")); - if (src != null && src.indexOf(urlJS) !== -1) { - alreadyExists = true; - existingScript = scripts[i]; - } - } - if (!alreadyExists) { - let script = document.createElement("script"); - script.type = "text/javascript"; - script.src = urlJS; - script.setAttribute("data-by-n1ed", "true"); - document.getElementsByTagName("head")[0].appendChild(script); - return script; - } else { - return null; - } - } + return button; + } ); + } } diff --git a/src/new/assets/lib/flmngr/src/flmngrcommand.js b/src/new/assets/lib/flmngr/src/flmngrcommand.js deleted file mode 100644 index 7180cc728..000000000 --- a/src/new/assets/lib/flmngr/src/flmngrcommand.js +++ /dev/null @@ -1,205 +0,0 @@ -import { Command, findAttributeRange, first } from 'ckeditor5'; -import {showWarning} from "./utils.js"; - -export default class FlmngrCommand extends Command { - - static flmngr; - - imageExtensions = ['jpeg', 'jpg', 'png', 'bmp', 'svg', 'webp']; - - constructor( editor ) { - super( editor ); - - // Remove default document listener to lower its priority. - this.stopListening( this.editor.model.document, 'change' ); - - // Lower this command listener priority to be sure that refresh() will be called after link & image refresh. - this.listenTo( this.editor.model.document, 'change', () => this.refresh(), { priority: 'low' } ); - } - - refresh() { - const imageCommand = this.editor.commands.get( 'insertImage' ); - const linkCommand = this.editor.commands.get( 'link' ); - this.isEnabled = !imageCommand || // if there is no image command, the button IS always enabled: we will show a message - (imageCommand.isEnabled || (!!linkCommand && linkCommand.isEnabled)); - } - - isImage(filepath) { - let i = filepath.lastIndexOf("."); - if (i > -1 && i < filepath.length-1) { - let ext = filepath.substr(i + 1).toLowerCase(); - return ext === 'jpeg' || ext === 'jpg' || ext === 'png' || ext === 'gif' || ext === "bmp" || ext === "svg" || ext === "webp"; - } - return false; - } - - // Call a dialog to select local file and upload them ("Upload" action) - executeUpload() { - this.execute2(true); - } - - // Call Flmngr ("Browse" action) - execute() { - this.execute2(false); - } - - execute2(doUpload) { // false = browse - - const imageCommand = this.editor.commands.get( 'insertImage' ); - if (!imageCommand) { - let msg = "Please enable CKEditor 5 `Image` plugin in order to use Flmngr file manager"; - if (!!window.Drupal) - msg += ":\n\nDrupal users must set `Image Upload` -> `Enable image uploads` checkbox on the page of CKEditor 5 text format"; - alert(msg); - return; - } - - - if (!FlmngrCommand.flmngr) { - // console.log("File manager is not loaded yet"); - // return; - } - - const selection = this.editor.model.document.selection; - const el = selection.getSelectedElement() || first( selection.getSelectedBlocks() ); - - let currentUrl = null; - let elA = null; - const position = selection.getFirstPosition(); - if ( selection.hasAttribute( 'linkHref' ) ) { - elA = findAttributeRange(position, 'linkHref', selection.getAttribute('linkHref'), this.editor.model).getItems().next().value.textNode; - currentUrl = elA.getAttribute("linkHref"); - } - - let elImg = null; - if (!!el && (el.name === 'imageBlock' || el.name === 'imageInline')) { - elImg = el; - currentUrl = elImg.getAttribute("src"); - elA = null; - } - - if (doUpload) { - FlmngrCommand.flmngr.selectFiles({ - acceptExtensions: !!elImg ? this.imageExtensions : null, - isMultiple: false, - onFinish: (files) => { - FlmngrCommand.flmngr.upload({ - filesOrLinks: files, - onFinish: (urls, paths) => { - this.createOrChange(el, elImg, elA, urls); - }, - onFail: (error) => { - showWarning(this.editor, 'Unable to upload files', true, error, false); - } - }); - } - }) - } else { - mediaBundleBrowser(context.$note.attr('id')); - FlmngrCommand.flmngr.pickFiles({ - acceptExtensions: !!elImg ? this.imageExtensions : null, - isMultiple: false, - list: currentUrl ? [currentUrl] : null, - onFinish: (files) => { - this.createOrChange(el, elImg, elA, files.map(f => f.url)); - } - }); - } - } - - createOrChange(el, elImg, elA, urls) { - if (!!elImg) { - this.changeImgSrc(elImg, FlmngrCommand.flmngr.getNoCacheUrl(urls[0])); - } else if (!!elA) { - this.changeAHref(elA, urls[0]); - } else { - // Create new IMG and A elements - let urlsImages = []; - let urlsFiles = []; - for (let url of urls) { - if (this.isImage(url)) - urlsImages.push(FlmngrCommand.flmngr.getNoCacheUrl(url)); - else - urlsFiles.push(url); - } - - for (const url of urlsFiles) - this.createNewA(url); - - for (const url of urlsImages) - this.createNewImg(url); - } - } - - createNewImg(url) { - this.editor.model.change( writer => { - - const imageCommand = this.editor.commands.get( 'insertImage' ); - - // Check if inserting an image is actually possible - it might be possible to only insert a link. - if ( !imageCommand.isEnabled ) { - showWarning(this.editor, 'Inserting image failed', true, 'Could not insert image at the current position.', true); - return; - } - - this.editor.execute( 'insertImage', { source: [url] } ); - - } ); - }; - - createNewA(url) { - this.editor.model.change( writer => { - const insertPosition = this.editor.model.document.selection.getFirstPosition(); - - const i = url.lastIndexOf("/"); - const filename = url.substr(i + 1); - const title = "Download " + filename; - - writer.insertText( title, { linkHref: url }, insertPosition ); - } ); - }; - - changeImgSrc(el, url) { - - this.editor.model.change( writer => { - writer.setAttribute("src", url, el); - writer.removeAttribute("srcset", el); - writer.removeAttribute("sizes", el); - - /* - In Drupal when using existing content with existing image, - CKEditor 5 sets also a custom HTML attribute "src", so - to change an image URL we need not only to set an - attribute "src" of a model of CKEditor 5, - but also and "src" attribute of HTML. - Probably this is a bug or a misconfiguration of - CKEditor 5 in Drupal 9/10. - */ - let attr = el.getAttribute("htmlAttributes"); - if (attr) { - delete attr.attributes.src; - delete attr.attributes.srcset; - delete attr.attributes.sizes; - writer.setAttribute("htmlAttributes", attr, el); - } - }); - - }; - - changeAHref(el, url) { - this.editor.model.change( writer => { - writer.setAttribute( 'linkHref', url, el ); - // TODO: probably change text - }); - }; - - isImage(filepath) { - let i = filepath.lastIndexOf("."); - if (i > -1 && i < filepath.length-1) { - let ext = filepath.substr(i + 1).toLowerCase(); - if (this.imageExtensions.indexOf(ext) > -1) - return true; - } - return false; - } -} diff --git a/src/new/assets/lib/flmngr/src/index.js b/src/new/assets/lib/flmngr/src/index.js deleted file mode 100644 index f02864fab..000000000 --- a/src/new/assets/lib/flmngr/src/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import Flmngr from './flmngr.js'; - -export default { - Flmngr -}; diff --git a/src/new/assets/lib/flmngr/src/uploadcommand.js b/src/new/assets/lib/flmngr/src/uploadcommand.js deleted file mode 100644 index 8f1e817b6..000000000 --- a/src/new/assets/lib/flmngr/src/uploadcommand.js +++ /dev/null @@ -1,12 +0,0 @@ - -import FlmngrCommand from "./flmngrcommand.js"; - -export default class UploadCommand extends FlmngrCommand { - - execute() { - const flmngrCommand = this.editor.commands.get( 'upload' ); - flmngrCommand.executeUpload(); - } - -} - diff --git a/src/new/assets/lib/flmngr/src/utils.js b/src/new/assets/lib/flmngr/src/utils.js deleted file mode 100644 index f9e031608..000000000 --- a/src/new/assets/lib/flmngr/src/utils.js +++ /dev/null @@ -1,25 +0,0 @@ - -export function showWarning( - editor, - title, - doLocalizeTitle, - message, - doLocalizeMessage -) { - const notification = editor.plugins.get( 'Notification' ); - const t = editor.locale.t; - if (!!notification) { - notification.showWarning( - doLocalizeMessage ? t(message) : message, - { - title: doLocalizeTitle ? t(title) : title, - namespace: 'flmngr' - } - ); - } else { - alert( - (doLocalizeTitle ? t(title) : title) + "\n\n" + - doLocalizeMessage ? t(message) : message - ); - } -} diff --git a/src/new/assets/tailwind/backend.js b/src/new/assets/tailwind/backend.js index 5f7f6d755..91e66bc9b 100644 --- a/src/new/assets/tailwind/backend.js +++ b/src/new/assets/tailwind/backend.js @@ -4,7 +4,6 @@ import persist from '@alpinejs/persist' import $ from 'jquery' window.$ = window.jQuery = $; import { initTabs } from 'david-ai'; - // Initialize tabs functionality initTabs(); import { registerVueControllerComponents } from '@symfony/ux-vue'; diff --git a/src/new/composer.json b/src/new/composer.json index 793f39e7b..fff4499b7 100755 --- a/src/new/composer.json +++ b/src/new/composer.json @@ -93,6 +93,7 @@ "symfony/ux-autocomplete": "^2.14", "symfony/ux-chartjs": "^2.19", "symfony/ux-live-component": "^2.12", + "symfony/ux-turbo": "^2.24", "symfony/ux-twig-component": "^2.12", "symfony/ux-vue": "^2.23", "symfony/validator": "*", diff --git a/src/new/composer.lock b/src/new/composer.lock index 0fe3ba9df..c6c750948 100755 --- a/src/new/composer.lock +++ b/src/new/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a020910e9bff4a83b3f41207f9ff93ce", + "content-hash": "74118bc5e9236bf6ae9d7f1891c26692", "packages": [ { "name": "azuyalabs/yasumi", @@ -1394,26 +1394,29 @@ }, { "name": "doctrine/deprecations", - "version": "1.1.4", + "version": "1.1.5", "source": { "type": "git", "url": "https://github.com/doctrine/deprecations.git", - "reference": "31610dbb31faa98e6b5447b62340826f54fbc4e9" + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/31610dbb31faa98e6b5447b62340826f54fbc4e9", - "reference": "31610dbb31faa98e6b5447b62340826f54fbc4e9", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, + "conflict": { + "phpunit/phpunit": "<=7.5 || >=13" + }, "require-dev": { - "doctrine/coding-standard": "^9 || ^12", - "phpstan/phpstan": "1.4.10 || 2.0.3", + "doctrine/coding-standard": "^9 || ^12 || ^13", + "phpstan/phpstan": "1.4.10 || 2.1.11", "phpstan/phpstan-phpunit": "^1.0 || ^2", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12", "psr/log": "^1 || ^2 || ^3" }, "suggest": { @@ -1433,9 +1436,9 @@ "homepage": "https://www.doctrine-project.org/", "support": { "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/1.1.4" + "source": "https://github.com/doctrine/deprecations/tree/1.1.5" }, - "time": "2024-12-07T21:18:45+00:00" + "time": "2025-04-07T20:06:18+00:00" }, { "name": "doctrine/doctrine-bundle", @@ -3631,16 +3634,16 @@ }, { "name": "jms/serializer", - "version": "3.32.3", + "version": "3.32.4", "source": { "type": "git", "url": "https://github.com/schmittjoh/serializer.git", - "reference": "033c9beab9eb708509a3d400e9f0ffeb2d440e71" + "reference": "f5c6227b2664d1e75fda65f1e6c5686a0c034b31" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/033c9beab9eb708509a3d400e9f0ffeb2d440e71", - "reference": "033c9beab9eb708509a3d400e9f0ffeb2d440e71", + "url": "https://api.github.com/repos/schmittjoh/serializer/zipball/f5c6227b2664d1e75fda65f1e6c5686a0c034b31", + "reference": "f5c6227b2664d1e75fda65f1e6c5686a0c034b31", "shasum": "" }, "require": { @@ -3717,15 +3720,19 @@ ], "support": { "issues": "https://github.com/schmittjoh/serializer/issues", - "source": "https://github.com/schmittjoh/serializer/tree/3.32.3" + "source": "https://github.com/schmittjoh/serializer/tree/3.32.4" }, "funding": [ { "url": "https://github.com/goetas", "type": "github" + }, + { + "url": "https://github.com/scyzoryck", + "type": "github" } ], - "time": "2025-02-11T23:16:25+00:00" + "time": "2025-04-06T18:42:47+00:00" }, { "name": "jms/serializer-bundle", @@ -5787,16 +5794,16 @@ }, { "name": "nesbot/carbon", - "version": "3.8.6", + "version": "3.9.0", "source": { "type": "git", "url": "https://github.com/CarbonPHP/carbon.git", - "reference": "ff2f20cf83bd4d503720632ce8a426dc747bf7fd" + "reference": "6d16a8a015166fe54e22c042e0805c5363aef50d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/ff2f20cf83bd4d503720632ce8a426dc747bf7fd", - "reference": "ff2f20cf83bd4d503720632ce8a426dc747bf7fd", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/6d16a8a015166fe54e22c042e0805c5363aef50d", + "reference": "6d16a8a015166fe54e22c042e0805c5363aef50d", "shasum": "" }, "require": { @@ -5889,7 +5896,7 @@ "type": "tidelift" } ], - "time": "2025-02-20T17:33:38+00:00" + "time": "2025-03-27T12:57:33+00:00" }, { "name": "nicolab/php-ftp-client", @@ -12919,16 +12926,16 @@ }, { "name": "symfony/stimulus-bundle", - "version": "v2.23.0", + "version": "v2.24.0", "source": { "type": "git", "url": "https://github.com/symfony/stimulus-bundle.git", - "reference": "254f4e05cbaa349d4ae68b9b2e6a22995e0887f9" + "reference": "e09840304467cda3324cc116c7f4ee23c8ff227c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stimulus-bundle/zipball/254f4e05cbaa349d4ae68b9b2e6a22995e0887f9", - "reference": "254f4e05cbaa349d4ae68b9b2e6a22995e0887f9", + "url": "https://api.github.com/repos/symfony/stimulus-bundle/zipball/e09840304467cda3324cc116c7f4ee23c8ff227c", + "reference": "e09840304467cda3324cc116c7f4ee23c8ff227c", "shasum": "" }, "require": { @@ -12968,7 +12975,7 @@ "symfony-ux" ], "support": { - "source": "https://github.com/symfony/stimulus-bundle/tree/v2.23.0" + "source": "https://github.com/symfony/stimulus-bundle/tree/v2.24.0" }, "funding": [ { @@ -12984,7 +12991,7 @@ "type": "tidelift" } ], - "time": "2025-01-16T21:55:09+00:00" + "time": "2025-03-09T21:10:04+00:00" }, { "name": "symfony/string", @@ -13506,16 +13513,16 @@ }, { "name": "symfony/ux-autocomplete", - "version": "v2.23.0", + "version": "v2.24.0", "source": { "type": "git", "url": "https://github.com/symfony/ux-autocomplete.git", - "reference": "063926d4eeb07edec0789ef6f9b597fe9027102b" + "reference": "27379e70b6dc6079b0cef1c559217ba06a75f1a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/ux-autocomplete/zipball/063926d4eeb07edec0789ef6f9b597fe9027102b", - "reference": "063926d4eeb07edec0789ef6f9b597fe9027102b", + "url": "https://api.github.com/repos/symfony/ux-autocomplete/zipball/27379e70b6dc6079b0cef1c559217ba06a75f1a5", + "reference": "27379e70b6dc6079b0cef1c559217ba06a75f1a5", "shasum": "" }, "require": { @@ -13576,7 +13583,7 @@ "symfony-ux" ], "support": { - "source": "https://github.com/symfony/ux-autocomplete/tree/v2.23.0" + "source": "https://github.com/symfony/ux-autocomplete/tree/v2.24.0" }, "funding": [ { @@ -13592,20 +13599,20 @@ "type": "tidelift" } ], - "time": "2025-02-06T00:35:19+00:00" + "time": "2025-03-17T21:06:48+00:00" }, { "name": "symfony/ux-chartjs", - "version": "v2.23.0", + "version": "v2.24.0", "source": { "type": "git", "url": "https://github.com/symfony/ux-chartjs.git", - "reference": "bbe034301ac2a89855ec79d6d5123156071a50c0" + "reference": "8fe776864ef8e08225d509be9d49cc06b90d7043" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/ux-chartjs/zipball/bbe034301ac2a89855ec79d6d5123156071a50c0", - "reference": "bbe034301ac2a89855ec79d6d5123156071a50c0", + "url": "https://api.github.com/repos/symfony/ux-chartjs/zipball/8fe776864ef8e08225d509be9d49cc06b90d7043", + "reference": "8fe776864ef8e08225d509be9d49cc06b90d7043", "shasum": "" }, "require": { @@ -13656,7 +13663,7 @@ "symfony-ux" ], "support": { - "source": "https://github.com/symfony/ux-chartjs/tree/v2.23.0" + "source": "https://github.com/symfony/ux-chartjs/tree/v2.24.0" }, "funding": [ { @@ -13672,26 +13679,27 @@ "type": "tidelift" } ], - "time": "2025-01-05T13:18:49+00:00" + "time": "2025-03-09T21:10:04+00:00" }, { "name": "symfony/ux-live-component", - "version": "v2.23.0", + "version": "v2.24.0", "source": { "type": "git", "url": "https://github.com/symfony/ux-live-component.git", - "reference": "840542868a8473b49036ec1ed0c5238d14b075a8" + "reference": "ee1a8e5d01f5b3f2f8e6856941fa8c944677e41c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/ux-live-component/zipball/840542868a8473b49036ec1ed0c5238d14b075a8", - "reference": "840542868a8473b49036ec1ed0c5238d14b075a8", + "url": "https://api.github.com/repos/symfony/ux-live-component/zipball/ee1a8e5d01f5b3f2f8e6856941fa8c944677e41c", + "reference": "ee1a8e5d01f5b3f2f8e6856941fa8c944677e41c", "shasum": "" }, "require": { "php": ">=8.1", "symfony/deprecation-contracts": "^2.5|^3.0", "symfony/property-access": "^5.4.5|^6.0|^7.0", + "symfony/property-info": "^5.4|^6.0|^7.0", "symfony/stimulus-bundle": "^2.9", "symfony/ux-twig-component": "^2.8", "twig/twig": "^3.8.0" @@ -13712,7 +13720,6 @@ "symfony/framework-bundle": "^5.4|^6.0|^7.0", "symfony/options-resolver": "^5.4|^6.0|^7.0", "symfony/phpunit-bridge": "^6.1|^7.0", - "symfony/property-info": "^5.4|^6.0|^7.0", "symfony/security-bundle": "^5.4|^6.0|^7.0", "symfony/serializer": "^5.4|^6.0|^7.0", "symfony/twig-bundle": "^5.4|^6.0|^7.0", @@ -13750,7 +13757,7 @@ "twig" ], "support": { - "source": "https://github.com/symfony/ux-live-component/tree/v2.23.0" + "source": "https://github.com/symfony/ux-live-component/tree/v2.24.0" }, "funding": [ { @@ -13766,20 +13773,118 @@ "type": "tidelift" } ], - "time": "2025-02-07T23:57:34+00:00" + "time": "2025-03-12T08:41:47+00:00" }, { - "name": "symfony/ux-twig-component", - "version": "v2.23.0", + "name": "symfony/ux-turbo", + "version": "v2.24.0", "source": { "type": "git", - "url": "https://github.com/symfony/ux-twig-component.git", - "reference": "f29033b95e93aea2d498dc40eac185ed14b07800" + "url": "https://github.com/symfony/ux-turbo.git", + "reference": "22954300bd0b01ca46f17c7890ea15138d9cf67f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/ux-twig-component/zipball/f29033b95e93aea2d498dc40eac185ed14b07800", - "reference": "f29033b95e93aea2d498dc40eac185ed14b07800", + "url": "https://api.github.com/repos/symfony/ux-turbo/zipball/22954300bd0b01ca46f17c7890ea15138d9cf67f", + "reference": "22954300bd0b01ca46f17c7890ea15138d9cf67f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/stimulus-bundle": "^2.9.1" + }, + "conflict": { + "symfony/flex": "<1.13" + }, + "require-dev": { + "dbrekelmans/bdi": "dev-main", + "doctrine/doctrine-bundle": "^2.4.3", + "doctrine/orm": "^2.8 | 3.0", + "phpstan/phpstan": "^1.10", + "symfony/asset-mapper": "^6.4|^7.0", + "symfony/debug-bundle": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/form": "^5.4|^6.0|^7.0", + "symfony/framework-bundle": "^6.4|^7.0", + "symfony/mercure-bundle": "^0.3.7", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/panther": "^2.1", + "symfony/phpunit-bridge": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|6.3.*|^7.0", + "symfony/property-access": "^5.4|^6.0|^7.0", + "symfony/security-core": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/twig-bundle": "^6.4|^7.0", + "symfony/ux-twig-component": "^2.21", + "symfony/web-profiler-bundle": "^5.4|^6.0|^7.0" + }, + "type": "symfony-bundle", + "extra": { + "thanks": { + "url": "https://github.com/symfony/ux", + "name": "symfony/ux" + } + }, + "autoload": { + "psr-4": { + "Symfony\\UX\\Turbo\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kévin Dunglas", + "email": "kevin@dunglas.fr" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Hotwire Turbo integration for Symfony", + "homepage": "https://symfony.com", + "keywords": [ + "hotwire", + "javascript", + "mercure", + "symfony-ux", + "turbo", + "turbo-stream" + ], + "support": { + "source": "https://github.com/symfony/ux-turbo/tree/v2.24.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-04T17:29:20+00:00" + }, + { + "name": "symfony/ux-twig-component", + "version": "v2.24.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/ux-twig-component.git", + "reference": "48a46e4c6215d41cc97ba8dff0cff21ea9b255a8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/ux-twig-component/zipball/48a46e4c6215d41cc97ba8dff0cff21ea9b255a8", + "reference": "48a46e4c6215d41cc97ba8dff0cff21ea9b255a8", "shasum": "" }, "require": { @@ -13833,7 +13938,7 @@ "twig" ], "support": { - "source": "https://github.com/symfony/ux-twig-component/tree/v2.23.0" + "source": "https://github.com/symfony/ux-twig-component/tree/v2.24.0" }, "funding": [ { @@ -13849,20 +13954,20 @@ "type": "tidelift" } ], - "time": "2025-01-25T02:19:26+00:00" + "time": "2025-03-21T20:14:36+00:00" }, { "name": "symfony/ux-vue", - "version": "v2.23.0", + "version": "v2.24.0", "source": { "type": "git", "url": "https://github.com/symfony/ux-vue.git", - "reference": "d96995ea2214591114c7f76e807ae0ce34b439a5" + "reference": "69bea457266f425e33274a942d1c7e0d06021b73" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/ux-vue/zipball/d96995ea2214591114c7f76e807ae0ce34b439a5", - "reference": "d96995ea2214591114c7f76e807ae0ce34b439a5", + "url": "https://api.github.com/repos/symfony/ux-vue/zipball/69bea457266f425e33274a942d1c7e0d06021b73", + "reference": "69bea457266f425e33274a942d1c7e0d06021b73", "shasum": "" }, "require": { @@ -13913,7 +14018,7 @@ "symfony-ux" ], "support": { - "source": "https://github.com/symfony/ux-vue/tree/v2.23.0" + "source": "https://github.com/symfony/ux-vue/tree/v2.24.0" }, "funding": [ { @@ -13929,7 +14034,7 @@ "type": "tidelift" } ], - "time": "2024-12-05T14:25:02+00:00" + "time": "2025-03-09T21:10:04+00:00" }, { "name": "symfony/validator", @@ -17465,16 +17570,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.12.0", + "version": "3.12.1", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "2d1b63db139c3c6ea0c927698e5160f8b3b8d630" + "reference": "ea16a1f3719783345febd3aab41beb55c8c84bfd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/2d1b63db139c3c6ea0c927698e5160f8b3b8d630", - "reference": "2d1b63db139c3c6ea0c927698e5160f8b3b8d630", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/ea16a1f3719783345febd3aab41beb55c8c84bfd", + "reference": "ea16a1f3719783345febd3aab41beb55c8c84bfd", "shasum": "" }, "require": { @@ -17545,7 +17650,7 @@ "type": "thanks_dev" } ], - "time": "2025-03-18T05:04:51+00:00" + "time": "2025-04-04T12:57:55+00:00" }, { "name": "symfony/browser-kit", diff --git a/src/new/config/bundles.php b/src/new/config/bundles.php index aa4ee9e65..175133c58 100755 --- a/src/new/config/bundles.php +++ b/src/new/config/bundles.php @@ -64,4 +64,5 @@ return [ Symfonycasts\SassBundle\SymfonycastsSassBundle::class => ['all' => true], Dunglas\DoctrineJsonOdm\Bundle\DunglasDoctrineJsonOdmBundle::class => ['all' => true], Symfony\UX\Vue\VueBundle::class => ['all' => true], + Symfony\UX\Turbo\TurboBundle::class => ['all' => true], ]; diff --git a/src/new/importmap.php b/src/new/importmap.php index 9d128c252..830347a6e 100644 --- a/src/new/importmap.php +++ b/src/new/importmap.php @@ -382,4 +382,7 @@ return [ 'splitpanes' => [ 'version' => '4.0.3', ], + '@hotwired/turbo' => [ + 'version' => '7.3.0', + ], ]; diff --git a/src/new/src/PSC/Libraries/AceEditorBundle/Form/Extension/CKEditor5Type.php b/src/new/src/PSC/Libraries/AceEditorBundle/Form/Extension/CKEditor5Type.php index a2a4bc962..46f83d260 100644 --- a/src/new/src/PSC/Libraries/AceEditorBundle/Form/Extension/CKEditor5Type.php +++ b/src/new/src/PSC/Libraries/AceEditorBundle/Form/Extension/CKEditor5Type.php @@ -28,6 +28,7 @@ final class CKEditor5Type extends AbstractType $attr = $this->stimulusHelper->createStimulusAttributes(); $attr->addController('ckeditor5'); + $attr->addAttribute("flmg", '/media'); $view->vars['attr'] = $attr->toArray(); } diff --git a/src/new/src/PSC/Shop/MediaBundle/Controller/Backend/FolderController.php b/src/new/src/PSC/Shop/MediaBundle/Controller/Backend/FolderController.php index 3647a4d6f..663fb2f7f 100755 --- a/src/new/src/PSC/Shop/MediaBundle/Controller/Backend/FolderController.php +++ b/src/new/src/PSC/Shop/MediaBundle/Controller/Backend/FolderController.php @@ -50,11 +50,390 @@ use Symfony\Component\HttpFoundation\Request; */ class FolderController extends AbstractController { + #[Route(path: '/list/folder/cke/{htmlId}/{uuid}', defaults: ['uuid' => false, 'htmlId' => false], name: 'psc_shop_media_backend_folder_cke')] + #[Template] + public function ckeAction( + Request $request, + \PSC\Shop\MediaBundle\Helper\MediaManager $mediaManager, + \PSC\System\SettingsBundle\Service\Shop $shopService, + DocumentManager $documentManager, + PaginatorInterface $paginator, + $htmlId, + $uuid + ) { + + + $searchForm = $this->createForm(SearchType::class); + $session = $request->getSession(); + + + if ($uuid) { + $session->set('media-folder-uuid', $uuid); + } else { + if ($session->has('media-folder-uuid')) { + $uuid = $session->get('media-folder-uuid'); + ; + } + } + + $type = $request->get('type'); + /** + * @var AbstractMediaHandler $handler +*/ + $handler = null; + if ($type) { + $handler = $mediaManager->getHandlerForType($type); + } + + $searchForm->handleRequest($request); + /** + * @var \PSC\Shop\EntityBundle\Entity\Shop $selectedShop +*/ + $selectedShop = $shopService->getSelectedShop(); + $cat = new Folder(); + $folderForm = $this->createForm(FolderType::class, $cat); + $folderForm->handleRequest($request); + if ($folderForm->isSubmitted() && $folderForm->isValid()) { + $cat->setIcon($request->get('icon', 'fa-file')); + $documentManager->persist($cat); + $documentManager->flush(); + $session->set('media-folder-uuid', $cat->getId()); + $uuid = $cat->getId(); + } + + $subCat = new Folder(); + $subFolderForm = $this->createForm(SubFolderType::class, $subCat); + $subFolderForm->handleRequest($request); + + /** + * @var CachingIterator $folders +*/ + $folders = $documentManager + ->getRepository('PSC\Shop\MediaBundle\Document\Folder') + ->createQueryBuilder('folder') + ->field('parent_id')->exists(false) + ->sort('title', 'ASC')->getQuery()->execute(); + if (count($folders->toArray()) == 0) { + $this->createDefaultFolder($documentManager); + /** + * @var Folder[] $folders +*/ + $folders = $documentManager + ->getRepository('PSC\Shop\MediaBundle\Document\Folder') + ->createQueryBuilder('folder') + ->field('parent_id')->exists(false) + ->sort('title', 'ASC')->getQuery()->execute(); + } + + $level = 1; + + foreach ($folders as $cat) { + $subFolders = $documentManager + ->getRepository('PSC\Shop\MediaBundle\Document\Folder') + ->createQueryBuilder('folder') + ->field('parent_id')->equals($cat->getId()) + ->sort('title', 'ASC')->getQuery()->execute(); + $count = $documentManager + ->getRepository('PSC\Shop\MediaBundle\Document\Media') + ->createQueryBuilder('media') + ->field('folder.$id')->equals(new ObjectId($cat->getId()))->count() + ->getQuery()->execute(); + $cat->setMedia($count); + foreach($subFolders as $subFolder) { + $count = $documentManager + ->getRepository('PSC\Shop\MediaBundle\Document\Media') + ->createQueryBuilder('media') + ->field('folder.$id')->equals(new ObjectId($subFolder->getId()))->count() + ->getQuery()->execute(); + $subFolder->setMedia($count); + $cat->addSubFolder($subFolder); + $subSubFolders = $documentManager + ->getRepository('PSC\Shop\MediaBundle\Document\Folder') + ->createQueryBuilder('folder') + ->field('parent_id')->equals($subFolder->getId()) + ->sort('title', 'ASC')->getQuery()->execute(); + if($uuid == $subFolder->getId()) { + $level = 2; + } + foreach($subSubFolders as $subSubFolder) { + $count = $documentManager + ->getRepository('PSC\Shop\MediaBundle\Document\Media') + ->createQueryBuilder('media') + ->field('folder.$id')->equals(new ObjectId($subSubFolder->getId()))->count() + ->getQuery()->execute(); + $subSubFolder->setMedia($count); + $subFolder->addSubFolder($subSubFolder); + if($uuid == $subSubFolder->getId()) { + $level = 3; + } + } + } + } + + if (!$uuid) { + $folders->rewind(); + $uuid = $folders->current()->getId(); + } + + $selectedFolder = $documentManager + ->getRepository('PSC\Shop\MediaBundle\Document\Folder') + ->findOneBy(array('id' => $uuid)); + + if(!$selectedFolder) { + $selectedFolder = $documentManager + ->getRepository('PSC\Shop\MediaBundle\Document\Folder') + ->findOneBy([]); + } + + if ($subFolderForm->isSubmitted() && $subFolderForm->isValid()) { + $subCat->setIcon($request->get('icon', 'fa-file')); + $subCat->setParentId($selectedFolder->getId()); + $documentManager->persist($subCat); + $documentManager->flush(); + $session->set('media-folder-uuid', $subCat->getId()); + $uuid = $subCat->getId(); + $selectedFolder = $documentManager + ->getRepository('PSC\Shop\MediaBundle\Document\Folder') + ->findOneBy(array('id' => $uuid)); + return $this->redirectToRoute('psc_shop_media_backend_folder_show', ['uuid' => $uuid, 'htmlId' => $htmlId, 'modal' => $modal]); + } + $searchTerm = $request->query->get('term', ''); + $page = $request->query->getInt('page', 1); + if ($searchForm->isSubmitted() && $searchForm->isValid()) { + $searchTerm = $searchForm->get('term')->getData(); + $page = 1; + } else { + $searchForm->get('term')->setData($searchTerm); + } + + if ($searchTerm != "") { + $qb = $documentManager + ->getRepository('PSC\Shop\MediaBundle\Document\Media') + ->createQueryBuilder('media') + ->field('media.title')->where('function(){ return ((this.title && this.title.indexOf("' . $searchTerm . '") != -1) || (this.url && this.url.indexOf("' . $searchTerm . '") != -1)); }') + ->field('folder.$id')->equals(new ObjectId($selectedFolder->getId())) + ->sort('title', 'ASC'); + } else { + $qb = $documentManager + ->getRepository('PSC\Shop\MediaBundle\Document\Media') + ->createQueryBuilder('media') + ->field('folder.$id')->equals(new ObjectId($selectedFolder->getId())) + ->sort('title', 'ASC'); + } + + $pagination = $paginator->paginate($query = $qb->getQuery(), $page, 15); + $pagination->setParam('term', $searchTerm); + return array( + 'pagination' => $pagination, + 'mediamanager' => $mediaManager, + 'level' => $level, + 'folders' => $folders, + 'selectedFolder' => $selectedFolder, + 'folderForm' => $folderForm->createView(), + 'subFolderForm' => $subFolderForm->createView(), + 'modal' => true, + 'handler' => $handler, + 'htmlId' => $htmlId, + 'searchForm' => $searchForm->createView(), + ); + } + + + #[Route(path: '/list/folder/tw/{uuid}/{modal}/{htmlId}', defaults: ['uuid' => false, 'modal' => false, 'htmlId' => false], name: 'psc_shop_media_backend_folder_tw')] + #[Template] + public function twAction( + Request $request, + \PSC\Shop\MediaBundle\Helper\MediaManager $mediaManager, + \PSC\System\SettingsBundle\Service\Shop $shopService, + DocumentManager $documentManager, + PaginatorInterface $paginator, + $uuid, + $modal, + $htmlId + ) { + + + $searchForm = $this->createForm(SearchType::class); + $session = $request->getSession(); + + + if ($uuid) { + $session->set('media-folder-uuid', $uuid); + } else { + if ($session->has('media-folder-uuid')) { + $uuid = $session->get('media-folder-uuid'); + ; + } + } + + $type = $request->get('type'); + /** + * @var AbstractMediaHandler $handler +*/ + $handler = null; + if ($type) { + $handler = $mediaManager->getHandlerForType($type); + } + + $searchForm->handleRequest($request); + /** + * @var \PSC\Shop\EntityBundle\Entity\Shop $selectedShop +*/ + $selectedShop = $shopService->getSelectedShop(); + $cat = new Folder(); + $folderForm = $this->createForm(FolderType::class, $cat); + $folderForm->handleRequest($request); + if ($folderForm->isSubmitted() && $folderForm->isValid()) { + $cat->setIcon($request->get('icon', 'fa-file')); + $documentManager->persist($cat); + $documentManager->flush(); + $session->set('media-folder-uuid', $cat->getId()); + $uuid = $cat->getId(); + } + + $subCat = new Folder(); + $subFolderForm = $this->createForm(SubFolderType::class, $subCat); + $subFolderForm->handleRequest($request); + + /** + * @var CachingIterator $folders +*/ + $folders = $documentManager + ->getRepository('PSC\Shop\MediaBundle\Document\Folder') + ->createQueryBuilder('folder') + ->field('parent_id')->exists(false) + ->sort('title', 'ASC')->getQuery()->execute(); + if (count($folders->toArray()) == 0) { + $this->createDefaultFolder($documentManager); + /** + * @var Folder[] $folders +*/ + $folders = $documentManager + ->getRepository('PSC\Shop\MediaBundle\Document\Folder') + ->createQueryBuilder('folder') + ->field('parent_id')->exists(false) + ->sort('title', 'ASC')->getQuery()->execute(); + } + + $level = 1; + + foreach ($folders as $cat) { + $subFolders = $documentManager + ->getRepository('PSC\Shop\MediaBundle\Document\Folder') + ->createQueryBuilder('folder') + ->field('parent_id')->equals($cat->getId()) + ->sort('title', 'ASC')->getQuery()->execute(); + $count = $documentManager + ->getRepository('PSC\Shop\MediaBundle\Document\Media') + ->createQueryBuilder('media') + ->field('folder.$id')->equals(new ObjectId($cat->getId()))->count() + ->getQuery()->execute(); + $cat->setMedia($count); + foreach($subFolders as $subFolder) { + $count = $documentManager + ->getRepository('PSC\Shop\MediaBundle\Document\Media') + ->createQueryBuilder('media') + ->field('folder.$id')->equals(new ObjectId($subFolder->getId()))->count() + ->getQuery()->execute(); + $subFolder->setMedia($count); + $cat->addSubFolder($subFolder); + $subSubFolders = $documentManager + ->getRepository('PSC\Shop\MediaBundle\Document\Folder') + ->createQueryBuilder('folder') + ->field('parent_id')->equals($subFolder->getId()) + ->sort('title', 'ASC')->getQuery()->execute(); + if($uuid == $subFolder->getId()) { + $level = 2; + } + foreach($subSubFolders as $subSubFolder) { + $count = $documentManager + ->getRepository('PSC\Shop\MediaBundle\Document\Media') + ->createQueryBuilder('media') + ->field('folder.$id')->equals(new ObjectId($subSubFolder->getId()))->count() + ->getQuery()->execute(); + $subSubFolder->setMedia($count); + $subFolder->addSubFolder($subSubFolder); + if($uuid == $subSubFolder->getId()) { + $level = 3; + } + } + } + } + + if (!$uuid) { + $folders->rewind(); + $uuid = $folders->current()->getId(); + } + + $selectedFolder = $documentManager + ->getRepository('PSC\Shop\MediaBundle\Document\Folder') + ->findOneBy(array('id' => $uuid)); + + if(!$selectedFolder) { + $selectedFolder = $documentManager + ->getRepository('PSC\Shop\MediaBundle\Document\Folder') + ->findOneBy([]); + } + + if ($subFolderForm->isSubmitted() && $subFolderForm->isValid()) { + $subCat->setIcon($request->get('icon', 'fa-file')); + $subCat->setParentId($selectedFolder->getId()); + $documentManager->persist($subCat); + $documentManager->flush(); + $session->set('media-folder-uuid', $subCat->getId()); + $uuid = $subCat->getId(); + $selectedFolder = $documentManager + ->getRepository('PSC\Shop\MediaBundle\Document\Folder') + ->findOneBy(array('id' => $uuid)); + return $this->redirectToRoute('psc_shop_media_backend_folder_tw', ['uuid' => $uuid, 'htmlId' => $htmlId, 'modal' => $modal]); + } + $searchTerm = $request->query->get('term', ''); + $page = $request->query->getInt('page', 1); + if ($searchForm->isSubmitted() && $searchForm->isValid()) { + $searchTerm = $searchForm->get('term')->getData(); + $page = 1; + } else { + $searchForm->get('term')->setData($searchTerm); + } + + if ($searchTerm != "") { + $qb = $documentManager + ->getRepository('PSC\Shop\MediaBundle\Document\Media') + ->createQueryBuilder('media') + ->field('media.title')->where('function(){ return ((this.title && this.title.indexOf("' . $searchTerm . '") != -1) || (this.url && this.url.indexOf("' . $searchTerm . '") != -1)); }') + ->field('folder.$id')->equals(new ObjectId($selectedFolder->getId())) + ->sort('title', 'ASC'); + } else { + $qb = $documentManager + ->getRepository('PSC\Shop\MediaBundle\Document\Media') + ->createQueryBuilder('media') + ->field('folder.$id')->equals(new ObjectId($selectedFolder->getId())) + ->sort('title', 'ASC'); + } + + $pagination = $paginator->paginate($query = $qb->getQuery(), $page, 15); + $pagination->setParam('term', $searchTerm); + return array( + 'pagination' => $pagination, + 'mediamanager' => $mediaManager, + 'level' => $level, + 'folders' => $folders, + 'selectedFolder' => $selectedFolder, + 'folderForm' => $folderForm->createView(), + 'subFolderForm' => $subFolderForm->createView(), + 'modal' => $modal, + 'handler' => $handler, + 'htmlId' => $htmlId, + 'searchForm' => $searchForm->createView(), + ); + } + + + /** * Default Seite * - * - * @param Request $request + * @param Request $request * @return array */ #[Route(path: '/list/folder/show/{uuid}/{modal}/{htmlId}', defaults: ['uuid' => false, 'modal' => false, 'htmlId' => false], name: 'psc_shop_media_backend_folder_show')] @@ -85,14 +464,18 @@ class FolderController extends AbstractController } $type = $request->get('type'); - /** @var AbstractMediaHandler $handler */ + /** + * @var AbstractMediaHandler $handler +*/ $handler = null; if ($type) { $handler = $mediaManager->getHandlerForType($type); } $searchForm->handleRequest($request); - /** @var \PSC\Shop\EntityBundle\Entity\Shop $selectedShop */ + /** + * @var \PSC\Shop\EntityBundle\Entity\Shop $selectedShop +*/ $selectedShop = $shopService->getSelectedShop(); $cat = new Folder(); $folderForm = $this->createForm(FolderType::class, $cat); @@ -109,15 +492,19 @@ class FolderController extends AbstractController $subFolderForm = $this->createForm(SubFolderType::class, $subCat); $subFolderForm->handleRequest($request); - /** @var CachingIterator $folders */ + /** + * @var CachingIterator $folders +*/ $folders = $documentManager ->getRepository('PSC\Shop\MediaBundle\Document\Folder') ->createQueryBuilder('folder') - ->field('parent_id')->exists(false) + ->field('parent_id')->exists(false) ->sort('title', 'ASC')->getQuery()->execute(); if (count($folders->toArray()) == 0) { $this->createDefaultFolder($documentManager); - /** @var Folder[] $folders */ + /** + * @var Folder[] $folders +*/ $folders = $documentManager ->getRepository('PSC\Shop\MediaBundle\Document\Folder') ->createQueryBuilder('folder') @@ -242,7 +629,9 @@ class FolderController extends AbstractController #[Template] public function deleteAction(Request $request, \PSC\System\SettingsBundle\Service\Shop $shopService, DocumentManager $documentManager, $uuid, $modal, $htmlId) { - /** @var \PSC\Shop\EntityBundle\Entity\Shop $selectedShop */ + /** + * @var \PSC\Shop\EntityBundle\Entity\Shop $selectedShop +*/ $selectedShop = $shopService->getSelectedShop(); $folder = $documentManager ->getRepository('PSC\Shop\MediaBundle\Document\Folder') @@ -277,7 +666,6 @@ class FolderController extends AbstractController * @param Request $request * @param int $folderId * - * * @return array */ #[Route(path: '/list/folder/create', name: 'psc_shop_media_backend_folder_sub_create')] diff --git a/src/new/src/PSC/Shop/MediaBundle/DependencyInjection/Compiler/MediaHandlerCompilerPass.php b/src/new/src/PSC/Shop/MediaBundle/DependencyInjection/Compiler/MediaHandlerCompilerPass.php index f20cae2b5..bae7e4675 100755 --- a/src/new/src/PSC/Shop/MediaBundle/DependencyInjection/Compiler/MediaHandlerCompilerPass.php +++ b/src/new/src/PSC/Shop/MediaBundle/DependencyInjection/Compiler/MediaHandlerCompilerPass.php @@ -37,9 +37,11 @@ class MediaHandlerCompilerPass implements CompilerPassInterface if (!$container->hasParameter('twig.form.resources')) { return; } - $container->setParameter('twig.form.resources', array_merge( - array('@PSCShopMedia/form/media_image_widget.html.twig', '@PSCShopMedia/form/media_widget.html.twig'), - $container->getParameter('twig.form.resources') - )); + $container->setParameter( + 'twig.form.resources', array_merge( + array('@PSCShopMedia/form/media_image_widget.html.twig', '@PSCShopMedia/form/tw_media_widget.html.twig', '@PSCShopMedia/form/media_widget.html.twig'), + $container->getParameter('twig.form.resources') + ) + ); } } diff --git a/src/new/src/PSC/Shop/MediaBundle/Form/MediaForm.php b/src/new/src/PSC/Shop/MediaBundle/Form/MediaForm.php index 1515a0627..867b897cb 100644 --- a/src/new/src/PSC/Shop/MediaBundle/Form/MediaForm.php +++ b/src/new/src/PSC/Shop/MediaBundle/Form/MediaForm.php @@ -2,8 +2,10 @@ namespace PSC\Shop\MediaBundle\Form; +use PSC\Shop\MediaBundle\Form\Type\TWMediaType; use PSC\Shop\MediaBundle\Model\MediaItem; use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -12,13 +14,23 @@ class MediaForm extends AbstractType public function buildForm(FormBuilderInterface $builder, array $options): void { $builder - ->add('name', null, [ + ->add( + 'name', TextType::class, [ // added because setDescription() doesn't allow null // it would be simpler to make the arg to that method nullable + 'required' => false, 'empty_data' => '', - ]) - ->add('description') - ; + ] + ) + ->add( + 'media', TWMediaType::class, [ + // added because setDescription() doesn't allow null + // it would be simpler to make the arg to that method nullable + 'required' => false, + 'empty_data' => '', + ] + ) + ->add('description', TextType::class, ['required' => false]); } public function configureOptions(OptionsResolver $resolver): void diff --git a/src/new/src/PSC/Shop/MediaBundle/Form/Type/TWMediaType.php b/src/new/src/PSC/Shop/MediaBundle/Form/Type/TWMediaType.php new file mode 100644 index 000000000..e5f811164 --- /dev/null +++ b/src/new/src/PSC/Shop/MediaBundle/Form/Type/TWMediaType.php @@ -0,0 +1,107 @@ +mediaManager = $mediaManager; + $this->mongoManager = $mongoManager; + } + + /** + * Builds the form. + * + * This method is called for each type in the hierarchy starting form the + * top most type. Type extensions can further modify the form. + * + * @param FormBuilderInterface $builder The form builder + * @param array $options The options + * + * @see FormTypeExtensionInterface::buildForm() + */ + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder->addViewTransformer( + new IdToMediaTransformer($this->mongoManager, $options['current_value_container']), + true + ); + $builder->setAttribute('chooser', $options['chooser']); + $builder->setAttribute('mediatype', $options['mediatype']); + } + + /** + * @return string + */ + public function getParent() + { + return FormType::class; + } + + /** + * Sets the default options for this type. + * + * @param OptionsResolver $resolver The resolver for the options. + */ + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults( + array( + 'compound' => false, + 'chooser' => 'psc_shop_media_backend_folder_tw', + 'mediatype' => null, + 'current_value_container' => new CurrentValueContainer(), + ) + ); + } + + /** + * Returns the name of this type. + * + * @return string The name of this type + */ + public function getBlockPrefix(): string + { + return 'tw_media'; + } + + /** + * {@inheritdoc} + */ + public function buildView(FormView $view, FormInterface $form, array $options) + { + $view->vars['chooser'] = $form->getConfig()->getAttribute('chooser'); + $view->vars['mediatype'] = $form->getConfig()->getAttribute('mediatype'); + $view->vars['mediamanager'] = $this->mediaManager; + } +} diff --git a/src/new/src/PSC/Shop/MediaBundle/Model/MediaItem.php b/src/new/src/PSC/Shop/MediaBundle/Model/MediaItem.php index a19ea15f6..dddb363db 100644 --- a/src/new/src/PSC/Shop/MediaBundle/Model/MediaItem.php +++ b/src/new/src/PSC/Shop/MediaBundle/Model/MediaItem.php @@ -4,9 +4,16 @@ namespace PSC\Shop\MediaBundle\Model; class MediaItem { - public string $name; + public ?string $name; - public string $description; + public ?string $description; - public string $media; + public ?string $media; + + public function __construct() + { + $this->name = "Name"; + $this->description = ""; + } + } diff --git a/src/new/src/PSC/Shop/MediaBundle/Resources/config/services.yml b/src/new/src/PSC/Shop/MediaBundle/Resources/config/services.yml index 3f6df1181..fe1198edf 100755 --- a/src/new/src/PSC/Shop/MediaBundle/Resources/config/services.yml +++ b/src/new/src/PSC/Shop/MediaBundle/Resources/config/services.yml @@ -1,5 +1,6 @@ parameters: psc.shop.media.form.type.media.class: 'PSC\Shop\MediaBundle\Form\Type\MediaType' + psc.shop.media.form.type.twmedia.class: 'PSC\Shop\MediaBundle\Form\Type\TWMediaType' psc.shop.media.folder_manager.class: 'PSC\Shop\MediaBundle\Helper\FolderManager' services: @@ -49,10 +50,18 @@ services: public: true arguments: ['@doctrine_mongodb.odm.default_document_manager', '@@PSC\\System\\SettingsBundle\\Service\\Shop'] + form.type.twmedia: + class: '%psc.shop.media.form.type.twmedia.class%' + arguments: + - '@PSC\Shop\MediaBundle\Helper\MediaManager' + - '@doctrine_mongodb.odm.default_document_manager' + tags: + - { name: form.type} + form.type.media: class: '%psc.shop.media.form.type.media.class%' arguments: - '@PSC\Shop\MediaBundle\Helper\MediaManager' - '@doctrine_mongodb.odm.default_document_manager' tags: - - { name: form.type} \ No newline at end of file + - { name: form.type} diff --git a/src/new/src/PSC/Shop/MediaBundle/Resources/views/backend/folder/cke.html.twig b/src/new/src/PSC/Shop/MediaBundle/Resources/views/backend/folder/cke.html.twig new file mode 100644 index 000000000..e70d07e09 --- /dev/null +++ b/src/new/src/PSC/Shop/MediaBundle/Resources/views/backend/folder/cke.html.twig @@ -0,0 +1,193 @@ +{% extends 'backend_layout.html.twig' %} + +{% block header %} +
+
+
+

+ + Media > + Dashboard +

+
+
+
+{% endblock %} + +{% block appButtons %} + + +{% endblock %} + +{% block appContent %} +
+
+ {{ form_start(folderForm, { 'attr': {'class': ''}}) }} +
+
+ +
+ + {{ form_widget(folderForm.title, {attr: {'class': 'form-control'}}) }} + + + +
+
+
+ + + {{ form_end(folderForm) }} +
+ + +
+
+
+
{% if selectedFolder %}

{{ selectedFolder.title }} {{ selectedFolder.id }}

{% endif %}
+
+
+
+
{% if selectedFolder %} Dateien hinzufügen (Einzelupload) {% if pagination|length == 0 %} Ordner löschen{% endif %}{% endif %}
+
+ {{ form_start(searchForm, { 'attr': {'class': ''}}) }} +
+ {{ form_widget(searchForm.term) }} +
+ +
+
+ {{ form_end(searchForm) }} +
+
+ {% if level < 3 %} + {{ form_start(subFolderForm, { 'attr': {'class': ''}}) }} +
+
+ +
+ + {{ form_widget(subFolderForm.title, {attr: {'class': 'form-control'}}) }} + + + +
+
+
+ {{ form_end(subFolderForm) }} + {% endif %} +
+
+ + + + + + + + + + + + + {% for media in pagination %} + + {% set handler = mediamanager.getHandler(media) %} + {% set imageurlorg = handler.getImageUrl(media, app.request.basePath) %} + {% if imageurlorg is not empty and media.location == 'local' %} + {% if imageurlorg|lower|split('.')|last == 'svg' or 'image/svg' in media.contentType %} + {% set imageurlretina = imageurlorg %} + {% set imageurlinsert = imageurlorg %} + {% set isImage = false %} + {% else %} + {% set imageurlretina = asset(imageurlorg | imagine_filter('psc_backend_media_image')) %} + {% set imageurl = asset(imageurlorg | imagine_filter('psc_backend_media_image')) %} + {% set imageurlinsert = asset(imageurlorg | imagine_filter('psc_backend_media_summernote_image')) %} + {% set isImage = true %} + {% endif %} + {% else %} + {% set imageurlinsert = handler.getImageUrl(media, app.request.basePath) %} + {% set isImage = false %} + {% endif %} + + {% set path = "[%s]" | format("M" ~ media.id) %} + + + + + + + + {% endfor %} + +
{{ knp_pagination_sortable(pagination, 'Uid', 'uid') }}{{ knp_pagination_sortable(pagination, 'Titel', 'title') }}{{ knp_pagination_sortable(pagination, 'Erzeugt', 'createdAt') }}{{ knp_pagination_sortable(pagination, 'Dateiname', 'originalFilename') }}
+ {% if imageurlorg %} + {{ media.title }} + {% else %} + + {% endif %} + {{ media.id }}{{ media.title }}{{ media.createdAt|date("d.m.Y") }}{{ media.originalFilename }} + +
+ +
+
+
+
+{% endblock %} + +{% block scripts %} + +{% endblock %} diff --git a/src/new/src/PSC/Shop/MediaBundle/Resources/views/backend/folder/tw.html.twig b/src/new/src/PSC/Shop/MediaBundle/Resources/views/backend/folder/tw.html.twig new file mode 100644 index 000000000..7b34dd0c2 --- /dev/null +++ b/src/new/src/PSC/Shop/MediaBundle/Resources/views/backend/folder/tw.html.twig @@ -0,0 +1,157 @@ +{% extends 'modalFrame.html.twig' %} + +{% block body %} +
+
+ {{ form_start(folderForm, { 'attr': {'class': ''}}) }} +
+
+ +
+ + {{ form_widget(folderForm.title, {attr: {'class': 'form-control'}}) }} + + + +
+
+
+ + + {{ form_end(folderForm) }} +
+ + +
+
+
+
{% if selectedFolder %}

{{ selectedFolder.title }} {{ selectedFolder.id }}

{% endif %}
+
+
+
+
{% if selectedFolder %} Dateien hinzufügen (Einzelupload) {% if pagination|length == 0 %} Ordner löschen{% endif %}{% endif %}
+
+ {{ form_start(searchForm, { 'attr': {'class': ''}}) }} +
+ {{ form_widget(searchForm.term) }} +
+ +
+
+ {{ form_end(searchForm) }} +
+
+ {% if level < 3 %} + {{ form_start(subFolderForm, { 'attr': {'class': ''}}) }} +
+
+ +
+ + {{ form_widget(subFolderForm.title, {attr: {'class': 'form-control'}}) }} + + + +
+
+
+ {{ form_end(subFolderForm) }} + {% endif %} +
+
+ + + + + + + + + + + + + {% for media in pagination %} + + {% set handler = mediamanager.getHandler(media) %} + {% set imageurlorg = handler.getImageUrl(media, app.request.basePath) %} + {% if imageurlorg is not empty and media.location == 'local' %} + {% if imageurlorg|lower|split('.')|last == 'svg' or 'image/svg' in media.contentType %} + {% set imageurlretina = imageurlorg %} + {% set imageurlinsert = imageurlorg %} + {% set isImage = false %} + {% else %} + {% set imageurlretina = asset(imageurlorg | imagine_filter('psc_backend_media_image')) %} + {% set imageurl = asset(imageurlorg | imagine_filter('psc_backend_media_image')) %} + {% set imageurlinsert = asset(imageurlorg | imagine_filter('psc_backend_media_summernote_image')) %} + {% set isImage = true %} + {% endif %} + {% else %} + {% set imageurlinsert = handler.getImageUrl(media, app.request.basePath) %} + {% set isImage = false %} + {% endif %} + + {% set path = "[%s]" | format("M" ~ media.id) %} + + + + + + + + {% endfor %} + +
{{ knp_pagination_sortable(pagination, 'Uid', 'uid') }}{{ knp_pagination_sortable(pagination, 'Titel', 'title') }}{{ knp_pagination_sortable(pagination, 'Erzeugt', 'createdAt') }}{{ knp_pagination_sortable(pagination, 'Dateiname', 'originalFilename') }}
+ {% if imageurlorg %} + {{ media.title }} + {% else %} + + {% endif %} + {{ media.id }}{{ media.title }}{{ media.createdAt|date("d.m.Y") }}{{ media.originalFilename }} + {% if modal %} + {% if isImage %} + Einfügen + {% else %} + Einfügen + {% endif %} + {% endif %} + Tauschen + Bearbeiten + +
+ +
+
+
+
+{% endblock %} diff --git a/src/new/src/PSC/Shop/MediaBundle/Resources/views/form/media_widget.html.twig b/src/new/src/PSC/Shop/MediaBundle/Resources/views/form/media_widget.html.twig index 37e644174..2f4076274 100755 --- a/src/new/src/PSC/Shop/MediaBundle/Resources/views/form/media_widget.html.twig +++ b/src/new/src/PSC/Shop/MediaBundle/Resources/views/form/media_widget.html.twig @@ -59,13 +59,11 @@ - - {% endapply %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/src/new/src/PSC/Shop/MediaBundle/Resources/views/form/tw_media_widget.html.twig b/src/new/src/PSC/Shop/MediaBundle/Resources/views/form/tw_media_widget.html.twig new file mode 100644 index 000000000..b6fb5414a --- /dev/null +++ b/src/new/src/PSC/Shop/MediaBundle/Resources/views/form/tw_media_widget.html.twig @@ -0,0 +1,54 @@ +{% block tw_media_widget %} + {% apply spaceless %} +
+ + + + +
+
+ {% if(value.ent is defined) %} + {% set media = value.ent %} + {% set handler = mediamanager.getHandler(media) %} + {% set imageurl = handler.getImageUrl(media, app.request.basePath) %} + {% if imageurl is not empty and media.location == 'local' %} + {% if imageurl|lower|split('.')|last == 'svg' or 'image/svg' in media.contentType %} + {% set imageurlretina = imageurl %} + {% else %} + {% set imageurlretina = asset(imageurl | imagine_filter('media_list_thumbnail_retina')) %} + {% set imageurl = asset(imageurl | imagine_filter('media_list_thumbnail')) %} + {% endif %} + {% endif %} + {% if imageurl %} + {{ media.title }} +
+ {{ media.title }} +
+ {% else %} + +
+ {{ media.title }} +
+ {% endif %} + {% else %} + +
+ {% endif %} +
+ +
+ Auswählen + + + +
+ + {% endapply %} +{% endblock %} diff --git a/src/new/src/PSC/Shop/NewsBundle/Resources/views/components/NewsForm.html.twig b/src/new/src/PSC/Shop/NewsBundle/Resources/views/components/NewsForm.html.twig index eab687ebc..69eee299d 100644 --- a/src/new/src/PSC/Shop/NewsBundle/Resources/views/components/NewsForm.html.twig +++ b/src/new/src/PSC/Shop/NewsBundle/Resources/views/components/NewsForm.html.twig @@ -65,9 +65,6 @@
-
- Loading... -
{{ form_row(form.introduction)}}
@@ -81,6 +78,8 @@ Name Description + Media + @@ -92,6 +91,9 @@ {{ form_row(media_form.description) }} + + {{ form_row(media_form.media) }} + {{ form_row(media_form.vars.button_delete, {label: 'X', attr: {class: 'btn btn-outline-danger'}}) }} diff --git a/src/new/symfony.lock b/src/new/symfony.lock index 41e3434da..ab2ea8f55 100755 --- a/src/new/symfony.lock +++ b/src/new/symfony.lock @@ -937,6 +937,15 @@ "config/routes/ux_live_component.yaml" ] }, + "symfony/ux-turbo": { + "version": "2.24", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "2.19", + "ref": "9dd2778a116b6e5e01e5e1582d03d5a9e82630de" + } + }, "symfony/ux-twig-component": { "version": "v2.12.0" }, diff --git a/src/new/templates/backend_tailwind_base.html.twig b/src/new/templates/backend_tailwind_base.html.twig index b723b3002..b5fd2890f 100644 --- a/src/new/templates/backend_tailwind_base.html.twig +++ b/src/new/templates/backend_tailwind_base.html.twig @@ -20,6 +20,22 @@ +
+ +
+
+ +
+
+
+