Fixes
This commit is contained in:
parent
f9ce89f6e7
commit
43264fce3b
@ -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,
|
||||
|
||||
69
src/new/assets/controllers/modal_controller.js
Normal file
69
src/new/assets/controllers/modal_controller.js
Normal file
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
16
src/new/assets/lib/ckeditor.js
vendored
16
src/new/assets/lib/ckeditor.js
vendored
@ -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: {
|
||||
|
||||
@ -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 () {});
|
||||
}));
|
||||
@ -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;
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
import Flmngr from './flmngr.js';
|
||||
|
||||
export default {
|
||||
Flmngr
|
||||
};
|
||||
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -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';
|
||||
|
||||
@ -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": "*",
|
||||
|
||||
235
src/new/composer.lock
generated
235
src/new/composer.lock
generated
@ -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",
|
||||
|
||||
@ -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],
|
||||
];
|
||||
|
||||
@ -382,4 +382,7 @@ return [
|
||||
'splitpanes' => [
|
||||
'version' => '4.0.3',
|
||||
],
|
||||
'@hotwired/turbo' => [
|
||||
'version' => '7.3.0',
|
||||
],
|
||||
];
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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')]
|
||||
|
||||
@ -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')
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
107
src/new/src/PSC/Shop/MediaBundle/Form/Type/TWMediaType.php
Normal file
107
src/new/src/PSC/Shop/MediaBundle/Form/Type/TWMediaType.php
Normal file
@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
namespace PSC\Shop\MediaBundle\Form\Type;
|
||||
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Doctrine\ODM\MongoDB\DocumentManager;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use PSC\Shop\MediaBundle\Helper\MediaManager;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FormType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/**
|
||||
* MediaType
|
||||
*/
|
||||
class TWMediaType extends AbstractType
|
||||
{
|
||||
/**
|
||||
* @var MediaManager
|
||||
*/
|
||||
protected $mediaManager;
|
||||
|
||||
/**
|
||||
* @var \Doctrine\ODM\MongoDB\DocumentManager
|
||||
*/
|
||||
protected $mongoManager;
|
||||
|
||||
/**
|
||||
* @param MediaManager $mediaManager The media manager
|
||||
* @param EntityManagerInterface $objectManager The media manager
|
||||
* @param DocumentManager $mongoManager The media manager
|
||||
*/
|
||||
public function __construct(MediaManager $mediaManager, DocumentManager $mongoManager)
|
||||
{
|
||||
$this->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;
|
||||
}
|
||||
}
|
||||
@ -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 = "";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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}
|
||||
- { name: form.type}
|
||||
|
||||
@ -0,0 +1,193 @@
|
||||
{% extends 'backend_layout.html.twig' %}
|
||||
|
||||
{% block header %}
|
||||
<div class="header">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-6">
|
||||
<h3>
|
||||
<i class="fas fa-image"></i>
|
||||
Media <span>>
|
||||
Dashboard </span>
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block appButtons %}
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block appContent %}
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
{{ form_start(folderForm, { 'attr': {'class': ''}}) }}
|
||||
<div class="form-group form-group-sm row">
|
||||
<div class="col-md-12">
|
||||
<label>Neuen Ordner anlegen</label>
|
||||
<div class="input-group input-group-sm">
|
||||
|
||||
{{ form_widget(folderForm.title, {attr: {'class': 'form-control'}}) }}
|
||||
<span class="input-group-btn">
|
||||
<button type="submit" class="btn btn-default btn-sm"><i class="fa fa-save"></i></button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{{ form_end(folderForm) }}
|
||||
<hr/>
|
||||
|
||||
<ul class="nav nav-pills flex-column">
|
||||
{% for cat in folders %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if selectedFolder.id == cat.id %}active{% endif %}" href="{{ path('psc_shop_media_backend_folder_cke', {uuid: cat.id, htmlId: htmlId}) }}">
|
||||
<span class="badge bg-dark pull-right">({{ cat.media }})</span> <i class="fa {{ cat.icon }}"></i> {{ cat.title }}</a>
|
||||
{% if cat.subFolders|length > 0 %}
|
||||
<ul>
|
||||
{% for subCat in cat.subFolders %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if selectedFolder.id == subCat.id %}active{% endif %}" href="{{ path('psc_shop_media_backend_folder_cke', {uuid: subCat.id, htmlId: htmlId}) }}">
|
||||
<span class="badge bg-dark pull-right">({{ subCat.media }})</span> <i class="fa {{ subCat.icon }}"></i> {{ subCat.title }}</a>
|
||||
{% if subCat.subFolders|length > 0 %}
|
||||
<ul>
|
||||
{% for subSubCat in subCat.subFolders %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if selectedFolder.id == subSubCat.id %}active{% endif %}" href="{{ path('psc_shop_media_backend_folder_cke', {uuid: subSubCat.id, htmlId: htmlId}) }}">
|
||||
<span class="badge bg-dark pull-right">({{ subSubCat.media }})</span> <i class="fa {{ subSubCat.icon }}"></i> {{ subSubCat.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<div class="row">
|
||||
<div class="col-md-12">{% if selectedFolder %}<h3>{{ selectedFolder.title }} <small>{{ selectedFolder.id }}</small></h3>{% endif %}</div>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="row">
|
||||
<div class="col-md-6">{% if selectedFolder %}<a href="{{ path("psc_shop_media_backend_upload_add", {uuid: selectedFolder.id, modal: true, htmlId: htmlId}) }}" class="btn btn-info btn-sm"><span class="fa fa-edit"></span> Dateien hinzufügen (Einzelupload)</a> {% if pagination|length == 0 %} <a href="{{ path("psc_shop_media_backend_folder_delete", {uuid: selectedFolder.id, htmlId: htmlId}) }}" class="btn btn-danger btn-sm"><span class="fa fa-remove"></span> Ordner löschen</a>{% endif %}{% endif %}</div>
|
||||
<div class="col-md-6">
|
||||
{{ form_start(searchForm, { 'attr': {'class': ''}}) }}
|
||||
<div class="input-group input-group-sm mb-3">
|
||||
{{ form_widget(searchForm.term) }}
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-outline-secondary btn-sm" type="submit">Suche</button>
|
||||
</div>
|
||||
</div>
|
||||
{{ form_end(searchForm) }}
|
||||
</div>
|
||||
</div>
|
||||
{% if level < 3 %}
|
||||
{{ form_start(subFolderForm, { 'attr': {'class': ''}}) }}
|
||||
<div class="form-group form-group-sm row">
|
||||
<div class="col-md-12">
|
||||
<label>Neuen Unterordner anlegen</label>
|
||||
<div class="input-group input-group-sm">
|
||||
|
||||
{{ form_widget(subFolderForm.title, {attr: {'class': 'form-control'}}) }}
|
||||
<span class="input-group-btn">
|
||||
<button type="submit" class="btn btn-default btn-sm"><i class="fa fa-save"></i></button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ form_end(subFolderForm) }}
|
||||
{% endif %}
|
||||
<div class="panel">
|
||||
<div class="body">
|
||||
<table class="table">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>{{ knp_pagination_sortable(pagination, 'Uid', 'uid') }}</th>
|
||||
<th>{{ knp_pagination_sortable(pagination, 'Titel', 'title') }}</th>
|
||||
<th>{{ knp_pagination_sortable(pagination, 'Erzeugt', 'createdAt') }}</th>
|
||||
<th>{{ knp_pagination_sortable(pagination, 'Dateiname', 'originalFilename') }}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for media in pagination %}
|
||||
<tr {% if loop.index is odd %}class="color"{% endif %}>
|
||||
{% 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) %}
|
||||
<td>
|
||||
{% if imageurlorg %}
|
||||
<img src="{{ imageurl }}" srcset="{{ imageurl }} 1x {{ imageurlretina is defined ? ', ' ~ imageurlretina ~ " 2x" }}" alt="{{ media.title }}" class="media-thumbnail__img">
|
||||
{% else %}
|
||||
<i class="fas fa-file-o media-thumbnail__icon"></i>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ media.id }}</td>
|
||||
<td>{{ media.title }}</td>
|
||||
<td>{{ media.createdAt|date("d.m.Y") }}</td>
|
||||
<td>{{ media.originalFilename }}</td>
|
||||
<td class="text-end">
|
||||
<button class="btn btn-sm btn-success {% if isImage %}cke_insertImage{% else %}cke_insertFile{% endif %}" data-uuid="{{ media.id }}" data-src-html="{{ imageurl }}" data-src="{{ imageurlinsert }}">einfügen</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="navigation">
|
||||
{{ knp_pagination_render(pagination) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script type="module">
|
||||
import $ from 'jquery'
|
||||
$(document).ready(function() {
|
||||
{% if htmlId %}
|
||||
$(".cke_insertImage").click(function() {
|
||||
const event = new CustomEvent("{{ htmlId }}_insertImage", {detail: $(this).attr('data-src')});
|
||||
window.opener.dispatchEvent(event);
|
||||
window.close();
|
||||
});
|
||||
|
||||
$(".cke_insertFile").click(function() {
|
||||
window.opener.$('#{{ htmlId }}').summernote('createLink', {
|
||||
text: 'Link to File',
|
||||
url: $(this).attr('data-src'),
|
||||
newWindow: true
|
||||
});
|
||||
window.close();
|
||||
});
|
||||
|
||||
{% endif %}
|
||||
});
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
@ -0,0 +1,157 @@
|
||||
{% extends 'modalFrame.html.twig' %}
|
||||
|
||||
{% block body %}
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
{{ form_start(folderForm, { 'attr': {'class': ''}}) }}
|
||||
<div class="form-group form-group-sm row">
|
||||
<div class="col-md-12">
|
||||
<label>Neuen Ordner anlegen</label>
|
||||
<div class="input-group input-group-sm">
|
||||
|
||||
{{ form_widget(folderForm.title, {attr: {'class': 'form-control'}}) }}
|
||||
<span class="input-group-btn">
|
||||
<button type="submit" class="btn btn-default btn-sm"><i class="fa fa-save"></i></button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{{ form_end(folderForm) }}
|
||||
<hr/>
|
||||
|
||||
<ul class="nav nav-pills flex-column">
|
||||
{% for cat in folders %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if selectedFolder.id == cat.id %}active{% endif %}" href="{{ path('psc_shop_media_backend_folder_tw', {uuid: cat.id, modal: modal, htmlId: htmlId}) }}">
|
||||
<span class="badge bg-dark pull-right">({{ cat.media }})</span> <i class="fa {{ cat.icon }}"></i> {{ cat.title }}</a>
|
||||
{% if cat.subFolders|length > 0 %}
|
||||
<ul>
|
||||
{% for subCat in cat.subFolders %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if selectedFolder.id == subCat.id %}active{% endif %}" href="{{ path('psc_shop_media_backend_folder_tw', {uuid: subCat.id, modal: modal, htmlId: htmlId}) }}">
|
||||
<span class="badge bg-dark pull-right">({{ subCat.media }})</span> <i class="fa {{ subCat.icon }}"></i> {{ subCat.title }}</a>
|
||||
{% if subCat.subFolders|length > 0 %}
|
||||
<ul>
|
||||
{% for subSubCat in subCat.subFolders %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if selectedFolder.id == subSubCat.id %}active{% endif %}" href="{{ path('psc_shop_media_backend_folder_tw', {uuid: subSubCat.id, modal: modal, htmlId: htmlId}) }}">
|
||||
<span class="badge bg-dark pull-right">({{ subSubCat.media }})</span> <i class="fa {{ subSubCat.icon }}"></i> {{ subSubCat.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<div class="row">
|
||||
<div class="col-md-12">{% if selectedFolder %}<h3>{{ selectedFolder.title }} <small>{{ selectedFolder.id }}</small></h3>{% endif %}</div>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="row">
|
||||
<div class="col-md-6">{% if selectedFolder %}<a href="{{ path("psc_shop_media_backend_upload_add", {uuid: selectedFolder.id, modal: modal, htmlId: htmlId}) }}" class="btn btn-info btn-sm"><span class="fa fa-edit"></span> Dateien hinzufügen (Einzelupload)</a> {% if pagination|length == 0 %} <a href="{{ path("psc_shop_media_backend_folder_delete", {uuid: selectedFolder.id, modal: modal, htmlId: htmlId}) }}" class="btn btn-danger btn-sm"><span class="fa fa-remove"></span> Ordner löschen</a>{% endif %}{% endif %}</div>
|
||||
<div class="col-md-6">
|
||||
{{ form_start(searchForm, { 'attr': {'class': ''}}) }}
|
||||
<div class="input-group input-group-sm mb-3">
|
||||
{{ form_widget(searchForm.term) }}
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-outline-secondary btn-sm" type="submit">Suche</button>
|
||||
</div>
|
||||
</div>
|
||||
{{ form_end(searchForm) }}
|
||||
</div>
|
||||
</div>
|
||||
{% if level < 3 %}
|
||||
{{ form_start(subFolderForm, { 'attr': {'class': ''}}) }}
|
||||
<div class="form-group form-group-sm row">
|
||||
<div class="col-md-12">
|
||||
<label>Neuen Unterordner anlegen</label>
|
||||
<div class="input-group input-group-sm">
|
||||
|
||||
{{ form_widget(subFolderForm.title, {attr: {'class': 'form-control'}}) }}
|
||||
<span class="input-group-btn">
|
||||
<button type="submit" class="btn btn-default btn-sm"><i class="fa fa-save"></i></button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ form_end(subFolderForm) }}
|
||||
{% endif %}
|
||||
<div class="panel">
|
||||
<div class="body">
|
||||
<table class="table">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>{{ knp_pagination_sortable(pagination, 'Uid', 'uid') }}</th>
|
||||
<th>{{ knp_pagination_sortable(pagination, 'Titel', 'title') }}</th>
|
||||
<th>{{ knp_pagination_sortable(pagination, 'Erzeugt', 'createdAt') }}</th>
|
||||
<th>{{ knp_pagination_sortable(pagination, 'Dateiname', 'originalFilename') }}</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for media in pagination %}
|
||||
<tr {% if loop.index is odd %}class="color"{% endif %}>
|
||||
{% 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) %}
|
||||
<td>
|
||||
{% if imageurlorg %}
|
||||
<img src="{{ imageurl }}" srcset="{{ imageurl }} 1x {{ imageurlretina is defined ? ', ' ~ imageurlretina ~ " 2x" }}" alt="{{ media.title }}" class="media-thumbnail__img">
|
||||
{% else %}
|
||||
<i class="fas fa-file-o media-thumbnail__icon"></i>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ media.id }}</td>
|
||||
<td>{{ media.title }}</td>
|
||||
<td>{{ media.createdAt|date("d.m.Y") }}</td>
|
||||
<td>{{ media.originalFilename }}</td>
|
||||
<td class="text-end">
|
||||
{% if modal %}
|
||||
{% if isImage %}
|
||||
<a href="javascript:void(0)" alt="{{ media.originalFilename }}" class="js-url-chooser-media-select btn btn-primary btn-sm" data-thumb-path="{{ imageurl }}" data-path="{{ path }}" data-title="{{ media.title|escape('js') }}" data-id="{{ media.id }}">Einfügen</a>
|
||||
{% else %}
|
||||
<a href="javascript:void(0)" alt="{{ media.originalFilename }}" class="js-url-chooser-media-select btn btn-primary btn-sm" data-path="{{ path }}" data-title="{{ media.title|escape('js') }}" data-id="{{ media.id }}">Einfügen</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<a href="{{ path('psc_shop_media_backend_upload_swap', {folder: selectedFolder.id, media: media.id, modal: modal, htmlId: htmlId}) }}" class="btn btn-sm btn-warning">Tauschen</a>
|
||||
<a href="{{ path('psc_shop_media_backend_media_detail', {folder: selectedFolder.id, uuid: media.id, modal: modal, htmlId: htmlId}) }}" class="btn btn-sm btn-info">Bearbeiten</a>
|
||||
<button type="button" data-action="modal#useMedia" data-thumb-path="{{ imageurl }}" data-path="{{ path }}" data-title="{{ media.title|escape('js') }}" data-id="{{ media.id }}" data-html-id="{{ htmlId }}">Close</button>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="navigation">
|
||||
{{ knp_pagination_render(pagination) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@ -59,13 +59,11 @@
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal">
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="js-ajax-modal-body modal-body ajax-modal__body"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endapply %}
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
@ -0,0 +1,54 @@
|
||||
{% block tw_media_widget %}
|
||||
{% apply spaceless %}
|
||||
<div id="{{ id }}-widget" class="media-chooser {% if(value.ent is defined) %}media-chooser--choosen{% endif %}">
|
||||
<!-- Hidden input -->
|
||||
<input id="{{ id }}" type="hidden" name="{{ full_name }}" value="{% if(value.id is defined) %}{{ value.id }}{% endif %}">
|
||||
|
||||
<!-- Preview -->
|
||||
<div class="media-chooser__preview">
|
||||
<figure class="thumbnail">
|
||||
{% 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 %}
|
||||
<img src="{{ imageurl }}" srcset="{{ imageurl }} 1x, {{ imageurlretina is defined ? ', ' ~ imageurlretina ~ " 2x" }}" alt="{{ media.title }}" id="{{ id }}__preview__img" class="thumbnail-img media-chooser__preview__img">
|
||||
<figcaption id="{{ id }}__preview__title" class="media-chooser__preview__title">
|
||||
{{ media.title }}
|
||||
</figcaption>
|
||||
{% else %}
|
||||
<i class="fas fa-file-o media-thumbnail__icon"></i>
|
||||
<figcaption id="{{ id }}__preview__title" class="media-chooser__preview__title">
|
||||
{{ media.title }}
|
||||
</figcaption>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<img id="{{ id }}__preview__img" class="thumbnail-img media-chooser__preview__img">
|
||||
<figcaption id="{{ id }}__preview__title" class="media-chooser__preview__title"></figcaption>
|
||||
{% endif %}
|
||||
</figure>
|
||||
|
||||
</div>
|
||||
<a
|
||||
data-turbo-frame="modal"
|
||||
data-action="modal#mediaSelect"
|
||||
href="{{ path(chooser, {'uuid': 0, 'modal': 1, 'htmlId' : id}) }}"
|
||||
class="flex items-center space-x-1 bg-psc-500 hover:bg-blue-700 text-white text-sm font-bold px-4 rounded"
|
||||
>Auswählen</a>
|
||||
|
||||
<button type="button" id="{{ id }}__preview__del-btn" class="js-media-chooser-del-preview-btn btn btn-danger media-chooser__preview__del-btn" data-linked-id="{{ id }}">
|
||||
<i class="fa fa-trash"></i>
|
||||
</button>
|
||||
<!-- Select Button -->
|
||||
</div>
|
||||
|
||||
{% endapply %}
|
||||
{% endblock %}
|
||||
@ -65,9 +65,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full px-4">
|
||||
<div {{ vue_component('PackageSearch', {news: news}) }}>
|
||||
Loading...
|
||||
</div>
|
||||
{{ form_row(form.introduction)}}
|
||||
</div>
|
||||
</div>
|
||||
@ -81,6 +78,8 @@
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
<td>Description</td>
|
||||
<td>Media</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -92,6 +91,9 @@
|
||||
<td>
|
||||
{{ form_row(media_form.description) }}
|
||||
</td>
|
||||
<td>
|
||||
{{ form_row(media_form.media) }}
|
||||
</td>
|
||||
<td>
|
||||
{{ form_row(media_form.vars.button_delete, {label: 'X', attr: {class: 'btn btn-outline-danger'}}) }}
|
||||
</td>
|
||||
|
||||
@ -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"
|
||||
},
|
||||
|
||||
@ -20,6 +20,22 @@
|
||||
|
||||
</head>
|
||||
<body class="min-h-screen bg-slate-100 text-gray-900 overflow-y-auto dark:text-gray-100 dark:bg-gray-900 antialiased">
|
||||
<div
|
||||
data-controller="modal"
|
||||
data-action="turbo:before-cache@window->modal#close"
|
||||
>
|
||||
<dialog
|
||||
class="open:flex bg-gray-800 rounded-lg shadow-xl inset-0 w-full md:w-fit md:max-w-[50%] md:min-w-[50%] animate-fade-in backdrop:bg-slate-600 backdrop:opacity-80"
|
||||
data-modal-target="dialog"
|
||||
data-action="close->modal#close click->modal#clickOutside"
|
||||
>
|
||||
<div class="flex grow p-5">
|
||||
<div class="grow overflow-auto p-1">
|
||||
<turbo-frame id="modal" data-modal-target="dynamicContent"></turbo-frame>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
</div>
|
||||
<div class="flex h-full w-full overflow-x-clip">
|
||||
<div x-data x-show="$store.sideBar.isOpen" x-transition.opacity.500ms="" @click="$store.sideBar.close()" class="fixed inset-0 z-20 w-full h-full bg-gray-900/50 lg:hidden"></div>
|
||||
<aside x-data :class="$store.sideBar.isOpen ? 'translate-x-0 max-w-[20em] shadow-2xl lg:max-w-[var(--sidebar-width)]' : '-translate-x-full lg:translate-x-0 lg:max-w-[var(--collapsed-sidebar-width)] lg:shadow-2xl rtl:lg:-translate-x-0 rtl:translate-x-full'" class="fixed inset-y-0 left-0 z-20 flex h-screen flex-col overflow-hidden w-[var(--sidebar-width)] bg-white transition-all rtl:left-auto rtl:right-0 lg:z-0 lg:border-r rtl:lg:border-l rtl:lg:border-r-0 dark:bg-gray-800 dark:border-gray-700 -translate-x-full lg:translate-x-0 lg:shadow-2xl rtl:lg:-translate-x-0 rtl:translate-x-full">
|
||||
|
||||
3
src/new/templates/modalFrame.html.twig
Normal file
3
src/new/templates/modalFrame.html.twig
Normal file
@ -0,0 +1,3 @@
|
||||
<turbo-frame id="modal">
|
||||
{% block body %}{% endblock %}
|
||||
</turbo-frame>
|
||||
Loading…
Reference in New Issue
Block a user