commit
c09249bcbe
@ -11,57 +11,24 @@ import './styles/app.scss'
|
||||
import $ from 'jquery'
|
||||
import 'bootstrap'
|
||||
|
||||
// Dropzone stuff move to component
|
||||
import {Dropzone} from 'dropzone'
|
||||
|
||||
// TODO handle error (Chapter 26)
|
||||
const formElement = $('#dropzoneForm')
|
||||
if (formElement) {
|
||||
const previewContent = $('#preview-content').html()
|
||||
console.log(previewContent)
|
||||
const dropzone = new Dropzone('#dropzoneForm', {
|
||||
acceptedFiles: '.jpg, .jpeg, .png',
|
||||
maxFiles: 1,
|
||||
init: function () {
|
||||
this.hiddenFileInput.removeAttribute('multiple')
|
||||
this.on('maxfilesexceeded', (file) => {
|
||||
this.removeAllFiles()
|
||||
this.addFile(file)
|
||||
})
|
||||
this.on('error', (file, data) => {
|
||||
console.log('error');
|
||||
if (data.detail) {
|
||||
this.emit('error', file, data.detail)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
})
|
||||
console.log('filename', previewContent)
|
||||
const mockFile = { name: previewContent }
|
||||
console.log('file', mockFile)
|
||||
dropzone.displayExistingFile(mockFile)
|
||||
}
|
||||
|
||||
// End Dropzone stuff move to component
|
||||
// start the Stimulus application
|
||||
import './bootstrap'
|
||||
|
||||
//import './js/index'
|
||||
|
||||
// needed for legacy code
|
||||
//global.$ = $
|
||||
|
||||
if (window.matchMedia('(prefers-color-scheme)').media !== 'not all') {
|
||||
console.log('🎉 Dark mode is supported')
|
||||
console.log('🎉 Dark mode is supported')
|
||||
}
|
||||
|
||||
$(document).ready(() => {
|
||||
console.log('ready')
|
||||
$('#toggleSidebar').on('click', () => {
|
||||
const toggleIcon = $('#toggleIcon')
|
||||
toggleIcon.toggleClass('fa fa-lg fa-fw fa-caret-square-o-left')
|
||||
toggleIcon.toggleClass('fa fa-lg fa-fw fa-caret-square-o-right')
|
||||
$('#sidebar').toggleClass('active')
|
||||
})
|
||||
console.log('ready')
|
||||
$('#toggleSidebar').on('click', () => {
|
||||
const toggleIcon = $('#toggleIcon')
|
||||
toggleIcon.toggleClass('fa fa-lg fa-fw fa-caret-square-o-left')
|
||||
toggleIcon.toggleClass('fa fa-lg fa-fw fa-caret-square-o-right')
|
||||
$('#sidebar').toggleClass('active')
|
||||
})
|
||||
})
|
||||
|
||||
// start the Stimulus application
|
||||
//import './bootstrap'
|
||||
|
@ -1,4 +1,30 @@
|
||||
{
|
||||
"controllers": [],
|
||||
"controllers": {
|
||||
"@symfony/ux-cropperjs": {
|
||||
"cropper": {
|
||||
"enabled": true,
|
||||
"fetch": "eager",
|
||||
"autoimport": {
|
||||
"cropperjs/dist/cropper.min.css": true,
|
||||
"@symfony/ux-cropperjs/src/style.css": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@symfony/ux-dropzone": {
|
||||
"dropzone": {
|
||||
"enabled": true,
|
||||
"fetch": "eager",
|
||||
"autoimport": {
|
||||
"@symfony/ux-dropzone/src/style.css": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@symfony/ux-turbo": {
|
||||
"turbo-core": {
|
||||
"enabled": true,
|
||||
"fetch": "eager"
|
||||
}
|
||||
}
|
||||
},
|
||||
"entrypoints": []
|
||||
}
|
||||
|
@ -1,16 +0,0 @@
|
||||
import { Controller } from '@hotwired/stimulus';
|
||||
|
||||
/*
|
||||
* This is an example Stimulus controller!
|
||||
*
|
||||
* Any element with a data-controller="hello" attribute will cause
|
||||
* this controller to be executed. The name "hello" comes from the filename:
|
||||
* hello_controller.js -> "hello"
|
||||
*
|
||||
* Delete this file or adapt it for your use!
|
||||
*/
|
||||
export default class extends Controller {
|
||||
connect() {
|
||||
this.element.textContent = 'Hello Stimulus! Edit me in assets/controllers/hello_controller.js';
|
||||
}
|
||||
}
|
125
assets/controllers/upload-avatar_controller.js
Normal file
125
assets/controllers/upload-avatar_controller.js
Normal file
@ -0,0 +1,125 @@
|
||||
import { Controller } from '@hotwired/stimulus'
|
||||
import { Dropzone } from 'dropzone'
|
||||
import Cropper from 'cropperjs'
|
||||
|
||||
export default class extends Controller {
|
||||
static values = {
|
||||
avatarImage: String,
|
||||
userId: Number
|
||||
}
|
||||
|
||||
connect() {
|
||||
let avatarDropzone = new Dropzone('#avatarDropzone', {
|
||||
url: `/user/upload/avatar/${this.userIdValue}`,
|
||||
avatarUrl: this.avatarImageValue,
|
||||
acceptedFiles: '.jpg, .jpeg, .png, gif',
|
||||
maxFiles: 1,
|
||||
dictDefaultMessage: '',
|
||||
init() {
|
||||
avatarDropzone = this
|
||||
// If the thumbnail is already in the right size on your server:
|
||||
const mockFile = { name: 'Filename', size: 12345 }
|
||||
const callback = null // Optional callback when it's done
|
||||
const crossOrigin = null // Added to the `img` tag for crossOrigin handling
|
||||
const resizeThumbnail = false // Tells Dropzone whether it should resize the image first
|
||||
avatarDropzone.displayExistingFile(
|
||||
mockFile,
|
||||
avatarDropzone.options.avatarUrl,
|
||||
callback,
|
||||
crossOrigin,
|
||||
resizeThumbnail
|
||||
)
|
||||
avatarDropzone.files.push(mockFile) // line missing in official docs
|
||||
},
|
||||
transformFile(file, done) {
|
||||
// Create the image editor overlay
|
||||
const editor = document.createElement('div')
|
||||
editor.style.position = 'fixed'
|
||||
editor.style.left = '25px'
|
||||
editor.style.right = '25px'
|
||||
editor.style.top = '25px'
|
||||
editor.style.bottom = '25px'
|
||||
editor.style.zIndex = '9999'
|
||||
editor.style.borderRadius = '15px;'
|
||||
editor.style.borderColor = '#FF8844'
|
||||
editor.style.backgroundColor = '#000'
|
||||
document.body.appendChild(editor)
|
||||
|
||||
// Create an image node for Cropper.js
|
||||
const image = new Image()
|
||||
image.src = URL.createObjectURL(file)
|
||||
editor.appendChild(image)
|
||||
|
||||
// Create Cropper.js
|
||||
const cropper = new Cropper(image, { aspectRatio: 1 })
|
||||
|
||||
// Create confirm button at the top left of the viewport
|
||||
const buttonCrop = document.createElement('button')
|
||||
buttonCrop.style.position = 'absolute'
|
||||
buttonCrop.style.right = '10px'
|
||||
buttonCrop.style.bottom = '50px'
|
||||
buttonCrop.style.zIndex = '9999'
|
||||
buttonCrop.textContent = 'Crop'
|
||||
buttonCrop.className = 'btn btn-secondary'
|
||||
editor.appendChild(buttonCrop)
|
||||
buttonCrop.addEventListener('click', () => {
|
||||
// clear preview
|
||||
//formElement.style.backgroundImage = ''
|
||||
|
||||
const canvas = cropper.getCroppedCanvas({
|
||||
width: 256,
|
||||
height: 256
|
||||
})
|
||||
canvas.toBlob((blob) => {
|
||||
avatarDropzone.createThumbnail(
|
||||
blob,
|
||||
avatarDropzone.options.thumbnailWidth,
|
||||
avatarDropzone.options.thumbnailHeight,
|
||||
avatarDropzone.options.thumbnailMethod,
|
||||
false,
|
||||
(dataURL) => {
|
||||
avatarDropzone.emit('thumbnail', file, dataURL)
|
||||
done(blob)
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
// Remove the editor from the view
|
||||
document.body.removeChild(editor)
|
||||
})
|
||||
|
||||
// Create keep original button
|
||||
const buttonKeep = document.createElement('button')
|
||||
buttonKeep.style.position = 'absolute'
|
||||
buttonKeep.style.right = '100px'
|
||||
buttonKeep.style.bottom = '50px'
|
||||
buttonKeep.style.zIndex = '9999'
|
||||
buttonKeep.textContent = 'Keep Original'
|
||||
buttonKeep.className = 'btn btn-primary'
|
||||
buttonKeep.focus()
|
||||
editor.appendChild(buttonKeep)
|
||||
buttonKeep.addEventListener('click', () => {
|
||||
//formElement.style.backgroundImage = ''
|
||||
|
||||
// Remove the editor from the view
|
||||
this.removeAllFiles()
|
||||
|
||||
done(file)
|
||||
document.body.removeChild(editor)
|
||||
})
|
||||
|
||||
// info text
|
||||
const infoText = document.createElement('span')
|
||||
infoText.style.position = 'absolute'
|
||||
infoText.style.opacity = '0.5'
|
||||
infoText.style.left = '100px'
|
||||
infoText.style.bottom = '50px'
|
||||
infoText.style.display = 'inline:block'
|
||||
infoText.style.zIndex = '9999'
|
||||
infoText.textContent = 'Use mouse wheel/touchpad to adapt size'
|
||||
infoText.className = 'btn btn-secondary'
|
||||
editor.appendChild(infoText)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -27,9 +27,9 @@ $list-group-hover-bg: darken($list-group, 10%);
|
||||
$list-group-active-bg: $list-group;
|
||||
$list-group-action-active-bg: $list-group;
|
||||
|
||||
@import 'bootstrap/scss/bootstrap';
|
||||
@import '~bootstrap';
|
||||
@import 'dropzone/dist/dropzone';
|
||||
|
||||
@import 'cropperjs';
|
||||
@import './components/sidebar';
|
||||
|
||||
|
||||
@ -40,19 +40,35 @@ html, body {
|
||||
background: #0e0e10;
|
||||
}
|
||||
|
||||
// Dropzone
|
||||
|
||||
.dropzone .dz-preview.dz-image-preview {
|
||||
// Dropzone
|
||||
.dropzone .dz-preview {
|
||||
background: transparent !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.dropzone-container {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
}
|
||||
|
||||
.dropzone-preview-filename {
|
||||
word-wrap: anywhere;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.dropzone-preview-image {
|
||||
flex-basis: 0;
|
||||
min-width: 150px;
|
||||
max-width: 150px;
|
||||
min-height: 150px;
|
||||
max-height: 150px;
|
||||
}
|
||||
|
||||
.dz-image {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.article-author-img {
|
||||
width: 80px;
|
||||
margin: 15px;
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
|
||||
#main_content {
|
||||
overflow-y: auto;
|
||||
|
@ -16,6 +16,8 @@
|
||||
"league/commonmark": "^2.3",
|
||||
"liip/imagine-bundle": "^2.9",
|
||||
"nelmio/cors-bundle": "^2.2",
|
||||
"php-flasher/flasher-sweetalert-symfony": "^1.7",
|
||||
"php-flasher/flasher-symfony": "^1.7",
|
||||
"phpdocumentor/reflection-docblock": "^5.3",
|
||||
"phpstan/phpdoc-parser": "^1.4",
|
||||
"rector/rector": "^0.12.21",
|
||||
@ -48,6 +50,9 @@
|
||||
"symfony/string": "6.1.*",
|
||||
"symfony/translation": "6.1.*",
|
||||
"symfony/twig-bundle": "6.1.*",
|
||||
"symfony/ux-cropperjs": "^2.5",
|
||||
"symfony/ux-dropzone": "^2.5",
|
||||
"symfony/ux-turbo": "^2.5",
|
||||
"symfony/validator": "6.1.*",
|
||||
"symfony/web-link": "6.1.*",
|
||||
"symfony/webapp-meta": "^1.0",
|
||||
@ -57,7 +62,8 @@
|
||||
"symfonycasts/verify-email-bundle": "^1.12",
|
||||
"twig/extra-bundle": "^3.4",
|
||||
"twig/markdown-extra": "^3.4",
|
||||
"twig/twig": "3.4.*"
|
||||
"twig/twig": "3.4.*",
|
||||
"ext-http": "*"
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
|
930
composer.lock
generated
930
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": "1c940d128112ec366d0f81bc6eccee45",
|
||||
"content-hash": "e475387f74f1428bb35d9943950aa2f8",
|
||||
"packages": [
|
||||
{
|
||||
"name": "dflydev/dot-access-data",
|
||||
@ -1689,6 +1689,125 @@
|
||||
],
|
||||
"time": "2022-10-17T19:48:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/psr7",
|
||||
"version": "2.4.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/psr7.git",
|
||||
"reference": "67c26b443f348a51926030c83481b85718457d3d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/67c26b443f348a51926030c83481b85718457d3d",
|
||||
"reference": "67c26b443f348a51926030c83481b85718457d3d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2.5 || ^8.0",
|
||||
"psr/http-factory": "^1.0",
|
||||
"psr/http-message": "^1.0",
|
||||
"ralouphie/getallheaders": "^3.0"
|
||||
},
|
||||
"provide": {
|
||||
"psr/http-factory-implementation": "1.0",
|
||||
"psr/http-message-implementation": "1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"bamarni/composer-bin-plugin": "^1.8.1",
|
||||
"http-interop/http-factory-tests": "^0.9",
|
||||
"phpunit/phpunit": "^8.5.29 || ^9.5.23"
|
||||
},
|
||||
"suggest": {
|
||||
"laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"bamarni-bin": {
|
||||
"bin-links": true,
|
||||
"forward-command": false
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-master": "2.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"GuzzleHttp\\Psr7\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Graham Campbell",
|
||||
"email": "hello@gjcampbell.co.uk",
|
||||
"homepage": "https://github.com/GrahamCampbell"
|
||||
},
|
||||
{
|
||||
"name": "Michael Dowling",
|
||||
"email": "mtdowling@gmail.com",
|
||||
"homepage": "https://github.com/mtdowling"
|
||||
},
|
||||
{
|
||||
"name": "George Mponos",
|
||||
"email": "gmponos@gmail.com",
|
||||
"homepage": "https://github.com/gmponos"
|
||||
},
|
||||
{
|
||||
"name": "Tobias Nyholm",
|
||||
"email": "tobias.nyholm@gmail.com",
|
||||
"homepage": "https://github.com/Nyholm"
|
||||
},
|
||||
{
|
||||
"name": "Márk Sági-Kazár",
|
||||
"email": "mark.sagikazar@gmail.com",
|
||||
"homepage": "https://github.com/sagikazarmark"
|
||||
},
|
||||
{
|
||||
"name": "Tobias Schultze",
|
||||
"email": "webmaster@tubo-world.de",
|
||||
"homepage": "https://github.com/Tobion"
|
||||
},
|
||||
{
|
||||
"name": "Márk Sági-Kazár",
|
||||
"email": "mark.sagikazar@gmail.com",
|
||||
"homepage": "https://sagikazarmark.hu"
|
||||
}
|
||||
],
|
||||
"description": "PSR-7 message implementation that also provides common utility methods",
|
||||
"keywords": [
|
||||
"http",
|
||||
"message",
|
||||
"psr-7",
|
||||
"request",
|
||||
"response",
|
||||
"stream",
|
||||
"uri",
|
||||
"url"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/guzzle/psr7/issues",
|
||||
"source": "https://github.com/guzzle/psr7/tree/2.4.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/GrahamCampbell",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/Nyholm",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-10-26T14:07:24+00:00"
|
||||
},
|
||||
{
|
||||
"name": "imagine/imagine",
|
||||
"version": "1.3.2",
|
||||
@ -1751,6 +1870,90 @@
|
||||
},
|
||||
"time": "2022-04-01T11:58:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "intervention/image",
|
||||
"version": "2.7.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Intervention/image.git",
|
||||
"reference": "04be355f8d6734c826045d02a1079ad658322dad"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Intervention/image/zipball/04be355f8d6734c826045d02a1079ad658322dad",
|
||||
"reference": "04be355f8d6734c826045d02a1079ad658322dad",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-fileinfo": "*",
|
||||
"guzzlehttp/psr7": "~1.1 || ^2.0",
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "~0.9.2",
|
||||
"phpunit/phpunit": "^4.8 || ^5.7 || ^7.5.15"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-gd": "to use GD library based image processing.",
|
||||
"ext-imagick": "to use Imagick based image processing.",
|
||||
"intervention/imagecache": "Caching extension for the Intervention Image library"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.4-dev"
|
||||
},
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Intervention\\Image\\ImageServiceProvider"
|
||||
],
|
||||
"aliases": {
|
||||
"Image": "Intervention\\Image\\Facades\\Image"
|
||||
}
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Intervention\\Image\\": "src/Intervention/Image"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Oliver Vogel",
|
||||
"email": "oliver@intervention.io",
|
||||
"homepage": "https://intervention.io/"
|
||||
}
|
||||
],
|
||||
"description": "Image handling and manipulation library with support for Laravel integration",
|
||||
"homepage": "http://image.intervention.io/",
|
||||
"keywords": [
|
||||
"gd",
|
||||
"image",
|
||||
"imagick",
|
||||
"laravel",
|
||||
"thumbnail",
|
||||
"watermark"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Intervention/image/issues",
|
||||
"source": "https://github.com/Intervention/image/tree/2.7.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://paypal.me/interventionio",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/Intervention",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-05-21T17:30:32+00:00"
|
||||
},
|
||||
{
|
||||
"name": "knplabs/knp-time-bundle",
|
||||
"version": "v1.20.0",
|
||||
@ -2489,6 +2692,316 @@
|
||||
},
|
||||
"time": "2022-09-12T23:36:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-flasher/flasher",
|
||||
"version": "v1.7.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-flasher/flasher.git",
|
||||
"reference": "10071abc73d0311a99e1860e88d5895ac4d7535c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-flasher/flasher/zipball/10071abc73d0311a99e1860e88d5895ac4d7535c",
|
||||
"reference": "10071abc73d0311a99e1860e88d5895ac4d7535c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Flasher\\Prime\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Younes KHOUBZA",
|
||||
"email": "younes.khoubza@gmail.com",
|
||||
"homepage": "https://www.linkedin.com/in/younes-khoubza",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "A powerful and flexible flash notification system for PHP",
|
||||
"homepage": "https://php-flasher.io",
|
||||
"keywords": [
|
||||
"Flasher",
|
||||
"alerts",
|
||||
"flash",
|
||||
"laravel",
|
||||
"lumen",
|
||||
"messages",
|
||||
"notifications",
|
||||
"notify",
|
||||
"noty",
|
||||
"notyf",
|
||||
"php",
|
||||
"pnotify",
|
||||
"sweet alert",
|
||||
"symfony",
|
||||
"toastr"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-flasher/flasher/tree/v1.7.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://www.paypal.com/paypalme/yoeunes",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://ko-fi.com/yoeunes",
|
||||
"type": "ko_fi"
|
||||
},
|
||||
{
|
||||
"url": "https://opencollective.com/php-flasher",
|
||||
"type": "open_collective"
|
||||
},
|
||||
{
|
||||
"url": "https://www.patreon.com/yoeunes",
|
||||
"type": "patreon"
|
||||
}
|
||||
],
|
||||
"time": "2022-07-05T19:33:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-flasher/flasher-sweetalert",
|
||||
"version": "v1.7.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-flasher/flasher-sweetalert.git",
|
||||
"reference": "abab36c6a70405ad9838238338a76853541baa34"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-flasher/flasher-sweetalert/zipball/abab36c6a70405ad9838238338a76853541baa34",
|
||||
"reference": "abab36c6a70405ad9838238338a76853541baa34",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3",
|
||||
"php-flasher/flasher": "^1.7"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Flasher\\SweetAlert\\Prime\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Younes KHOUBZA",
|
||||
"email": "younes.khoubza@gmail.com",
|
||||
"homepage": "https://www.linkedin.com/in/younes-khoubza",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "PHP Flasher adapter for Sweet Alert 2",
|
||||
"homepage": "https://php-flasher.io",
|
||||
"keywords": [
|
||||
"alerts",
|
||||
"laravel",
|
||||
"lumen",
|
||||
"messages",
|
||||
"notifications",
|
||||
"notify",
|
||||
"php",
|
||||
"pnotify",
|
||||
"sweetalert",
|
||||
"symfony"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-flasher/flasher-sweetalert/tree/v1.7.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://www.paypal.com/paypalme/yoeunes",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://ko-fi.com/yoeunes",
|
||||
"type": "ko_fi"
|
||||
},
|
||||
{
|
||||
"url": "https://opencollective.com/php-flasher",
|
||||
"type": "open_collective"
|
||||
},
|
||||
{
|
||||
"url": "https://www.patreon.com/yoeunes",
|
||||
"type": "patreon"
|
||||
}
|
||||
],
|
||||
"time": "2022-07-05T19:36:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-flasher/flasher-sweetalert-symfony",
|
||||
"version": "v1.7.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-flasher/flasher-sweetalert-symfony.git",
|
||||
"reference": "f8f10ad9760b30c8fc1fe4e9891b595a5cd8c51e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-flasher/flasher-sweetalert-symfony/zipball/f8f10ad9760b30c8fc1fe4e9891b595a5cd8c51e",
|
||||
"reference": "f8f10ad9760b30c8fc1fe4e9891b595a5cd8c51e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3",
|
||||
"php-flasher/flasher-sweetalert": "^1.7",
|
||||
"php-flasher/flasher-symfony": "^1.7"
|
||||
},
|
||||
"type": "symfony-bundle",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Flasher\\SweetAlert\\Symfony\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Younes KHOUBZA",
|
||||
"email": "younes.khoubza@gmail.com",
|
||||
"homepage": "https://www.linkedin.com/in/younes-khoubza",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "PHP Flasher Symfony adapter for Sweet Alert 2",
|
||||
"homepage": "https://php-flasher.io",
|
||||
"keywords": [
|
||||
"alerts",
|
||||
"bundle",
|
||||
"flex",
|
||||
"laravel",
|
||||
"lumen",
|
||||
"messages",
|
||||
"notifications",
|
||||
"notify",
|
||||
"php",
|
||||
"pnotify",
|
||||
"sweetalert",
|
||||
"symfony",
|
||||
"toastr",
|
||||
"yoeunes"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-flasher/flasher-sweetalert-symfony/tree/v1.7.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://www.paypal.com/paypalme/yoeunes",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://ko-fi.com/yoeunes",
|
||||
"type": "ko_fi"
|
||||
},
|
||||
{
|
||||
"url": "https://opencollective.com/php-flasher",
|
||||
"type": "open_collective"
|
||||
},
|
||||
{
|
||||
"url": "https://www.patreon.com/yoeunes",
|
||||
"type": "patreon"
|
||||
}
|
||||
],
|
||||
"time": "2022-07-05T19:36:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-flasher/flasher-symfony",
|
||||
"version": "v1.7.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-flasher/flasher-symfony.git",
|
||||
"reference": "1e003819402f415d07b8fedabfff527bd164822b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-flasher/flasher-symfony/zipball/1e003819402f415d07b8fedabfff527bd164822b",
|
||||
"reference": "1e003819402f415d07b8fedabfff527bd164822b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3",
|
||||
"php-flasher/flasher": "^1.7",
|
||||
"symfony/config": "^2.0|^3.0|^4.0|^5.0|^6.0",
|
||||
"symfony/console": "^2.0|^3.0|^4.0|^5.0|^6.0",
|
||||
"symfony/dependency-injection": "^2.0|^3.0|^4.0|^5.0|^6.0",
|
||||
"symfony/http-kernel": "^2.0|^3.0|^4.0|^5.0|^6.0",
|
||||
"symfony/translation": "^2.0|^3.0|^4.0|^5.0|^6.0",
|
||||
"symfony/twig-bundle": "^2.0|^3.0|^4.0|^5.0|^6.0"
|
||||
},
|
||||
"type": "symfony-bundle",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Flasher\\Symfony\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Younes KHOUBZA",
|
||||
"email": "younes.khoubza@gmail.com",
|
||||
"homepage": "https://www.linkedin.com/in/younes-khoubza",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "Symfony bundle integrating PHP Flasher into Symfony applications",
|
||||
"homepage": "https://php-flasher.io",
|
||||
"keywords": [
|
||||
"alerts",
|
||||
"bundle",
|
||||
"flex",
|
||||
"laravel",
|
||||
"lumen",
|
||||
"messages",
|
||||
"notifications",
|
||||
"notify",
|
||||
"php",
|
||||
"pnotify",
|
||||
"symfony",
|
||||
"toastr",
|
||||
"yoeunes"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-flasher/flasher-symfony/tree/v1.7.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://www.paypal.com/paypalme/yoeunes",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://ko-fi.com/yoeunes",
|
||||
"type": "ko_fi"
|
||||
},
|
||||
{
|
||||
"url": "https://opencollective.com/php-flasher",
|
||||
"type": "open_collective"
|
||||
},
|
||||
{
|
||||
"url": "https://www.patreon.com/yoeunes",
|
||||
"type": "patreon"
|
||||
}
|
||||
],
|
||||
"time": "2022-07-05T19:36:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/reflection-common",
|
||||
"version": "2.2.0",
|
||||
@ -2910,6 +3423,114 @@
|
||||
},
|
||||
"time": "2019-01-08T18:20:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-factory",
|
||||
"version": "1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/http-factory.git",
|
||||
"reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
|
||||
"reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.0.0",
|
||||
"psr/http-message": "^1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Http\\Message\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interfaces for PSR-7 HTTP message factories",
|
||||
"keywords": [
|
||||
"factory",
|
||||
"http",
|
||||
"message",
|
||||
"psr",
|
||||
"psr-17",
|
||||
"psr-7",
|
||||
"request",
|
||||
"response"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/http-factory/tree/master"
|
||||
},
|
||||
"time": "2019-04-30T12:38:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-message",
|
||||
"version": "1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/http-message.git",
|
||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Http\\Message\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for HTTP messages",
|
||||
"homepage": "https://github.com/php-fig/http-message",
|
||||
"keywords": [
|
||||
"http",
|
||||
"http-message",
|
||||
"psr",
|
||||
"psr-7",
|
||||
"request",
|
||||
"response"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/php-fig/http-message/tree/master"
|
||||
},
|
||||
"time": "2016-08-06T14:39:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/link",
|
||||
"version": "2.0.1",
|
||||
@ -3016,6 +3637,50 @@
|
||||
},
|
||||
"time": "2021-07-14T16:46:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ralouphie/getallheaders",
|
||||
"version": "3.0.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ralouphie/getallheaders.git",
|
||||
"reference": "120b605dfeb996808c31b6477290a714d356e822"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
|
||||
"reference": "120b605dfeb996808c31b6477290a714d356e822",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.6"
|
||||
},
|
||||
"require-dev": {
|
||||
"php-coveralls/php-coveralls": "^2.1",
|
||||
"phpunit/phpunit": "^5 || ^6.5"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/getallheaders.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ralph Khattar",
|
||||
"email": "ralph.khattar@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "A polyfill for getallheaders.",
|
||||
"support": {
|
||||
"issues": "https://github.com/ralouphie/getallheaders/issues",
|
||||
"source": "https://github.com/ralouphie/getallheaders/tree/develop"
|
||||
},
|
||||
"time": "2019-03-08T08:55:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "rector/rector",
|
||||
"version": "0.12.23",
|
||||
@ -8175,6 +8840,269 @@
|
||||
],
|
||||
"time": "2022-09-09T09:34:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/ux-cropperjs",
|
||||
"version": "v2.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/ux-cropperjs.git",
|
||||
"reference": "123b30ff6b539625bcf50413b945a16de6bc9d6e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/ux-cropperjs/zipball/123b30ff6b539625bcf50413b945a16de6bc9d6e",
|
||||
"reference": "123b30ff6b539625bcf50413b945a16de6bc9d6e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"intervention/image": "^2.5",
|
||||
"php": ">=7.2.5",
|
||||
"symfony/config": "^4.4.17|^5.0|^6.0",
|
||||
"symfony/dependency-injection": "^4.4.17|^5.0|^6.0",
|
||||
"symfony/form": "^4.4.17|^5.0|^6.0",
|
||||
"symfony/http-kernel": "^4.4.17|^5.0|^6.0",
|
||||
"symfony/validator": "^4.4.17|^5.0|^6.0"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/flex": "<1.13"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/framework-bundle": "^4.4.17|^5.0|^6.0",
|
||||
"symfony/phpunit-bridge": "^5.2|^6.0",
|
||||
"symfony/twig-bundle": "^4.4.17|^5.0|^6.0",
|
||||
"symfony/var-dumper": "^4.4.17|^5.0|^6.0"
|
||||
},
|
||||
"type": "symfony-bundle",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"name": "symfony/ux",
|
||||
"url": "https://github.com/symfony/ux"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\UX\\Cropperjs\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Titouan Galopin",
|
||||
"email": "galopintitouan@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Cropper.js integration for Symfony",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"symfony-ux"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/ux-cropperjs/tree/v2.5.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": "2022-11-01T17:19:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/ux-dropzone",
|
||||
"version": "v2.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/ux-dropzone.git",
|
||||
"reference": "897dbc3a8e61510c3f9c2ee7fee5596eb9cbf1d6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/ux-dropzone/zipball/897dbc3a8e61510c3f9c2ee7fee5596eb9cbf1d6",
|
||||
"reference": "897dbc3a8e61510c3f9c2ee7fee5596eb9cbf1d6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2.5",
|
||||
"symfony/config": "^4.4.17|^5.0|^6.0",
|
||||
"symfony/dependency-injection": "^4.4.17|^5.0|^6.0",
|
||||
"symfony/form": "^4.4.17|^5.0|^6.0",
|
||||
"symfony/http-kernel": "^4.4.17|^5.0|^6.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/framework-bundle": "^4.4.17|^5.0|^6.0",
|
||||
"symfony/phpunit-bridge": "^5.2|^6.0",
|
||||
"symfony/twig-bundle": "^4.4.17|^5.0|^6.0",
|
||||
"symfony/var-dumper": "^4.4.17|^5.0|^6.0"
|
||||
},
|
||||
"type": "symfony-bundle",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"name": "symfony/ux",
|
||||
"url": "https://github.com/symfony/ux"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\UX\\Dropzone\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Titouan Galopin",
|
||||
"email": "galopintitouan@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "File input dropzones for Symfony Forms",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"symfony-ux"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/ux-dropzone/tree/v2.5.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": "2022-09-08T14:28:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/ux-turbo",
|
||||
"version": "v2.5.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/ux-turbo.git",
|
||||
"reference": "3476bf0030937824137ad0aa1c9797d7c6085882"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/ux-turbo/zipball/3476bf0030937824137ad0aa1c9797d7c6085882",
|
||||
"reference": "3476bf0030937824137ad0aa1c9797d7c6085882",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2.5",
|
||||
"symfony/webpack-encore-bundle": "^1.11"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/flex": "<1.13"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/annotations": "^1.12",
|
||||
"doctrine/doctrine-bundle": "^2.2",
|
||||
"doctrine/orm": "^2.8 | 3.0",
|
||||
"phpstan/phpstan": "^0.12",
|
||||
"symfony/debug-bundle": "^5.2|^6.0",
|
||||
"symfony/expression-language": "^5.4|^6.0",
|
||||
"symfony/form": "^5.2|^6.0",
|
||||
"symfony/framework-bundle": "^5.2|^6.0",
|
||||
"symfony/mercure-bundle": "^0.3",
|
||||
"symfony/messenger": "^5.2|^6.0",
|
||||
"symfony/panther": "^1.0|^2.0",
|
||||
"symfony/phpunit-bridge": "^5.2.1|^6.0",
|
||||
"symfony/property-access": "^5.2|^6.0",
|
||||
"symfony/security-core": "^5.2|^6.0",
|
||||
"symfony/stopwatch": "^5.2|^6.0",
|
||||
"symfony/twig-bundle": "^5.2|^6.0",
|
||||
"symfony/web-profiler-bundle": "^5.2|^6.0"
|
||||
},
|
||||
"type": "symfony-bundle",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"name": "symfony/ux",
|
||||
"url": "https://github.com/symfony/ux"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\UX\\Turbo\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"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.5.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": "2022-09-08T14:28:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/validator",
|
||||
"version": "v6.1.7",
|
||||
|
@ -19,4 +19,9 @@ return [
|
||||
SymfonyCasts\Bundle\VerifyEmail\SymfonyCastsVerifyEmailBundle::class => ['all' => true],
|
||||
SymfonyCasts\Bundle\ResetPassword\SymfonyCastsResetPasswordBundle::class => ['all' => true],
|
||||
Liip\ImagineBundle\LiipImagineBundle::class => ['all' => true],
|
||||
Symfony\UX\Dropzone\DropzoneBundle::class => ['all' => true],
|
||||
Symfony\UX\Turbo\TurboBundle::class => ['all' => true],
|
||||
Flasher\Symfony\FlasherSymfonyBundle::class => ['all' => true],
|
||||
Flasher\SweetAlert\Symfony\FlasherSweetAlertSymfonyBundle::class => ['all' => true],
|
||||
Symfony\UX\Cropperjs\CropperjsBundle::class => ['all' => true],
|
||||
];
|
||||
|
@ -1,13 +1,15 @@
|
||||
# Documentation on how to configure the bundle can be found at: https://symfony.com/doc/current/bundles/LiipImagineBundle/basic-usage.html
|
||||
liip_imagine:
|
||||
# valid drivers options include "gd" or "gmagick" or "imagick"
|
||||
driver: "gd"
|
||||
driver: "imagick"
|
||||
twig:
|
||||
mode: lazy
|
||||
|
||||
filter_sets:
|
||||
squared_thumbnail_small:
|
||||
filters:
|
||||
thumbnail:
|
||||
size: [100, 100]
|
||||
size: [120, 120]
|
||||
mode: outbound
|
||||
allow_upscale: true
|
||||
squared_thumbnail_medium:
|
||||
|
31
migrations/Version20221115104149.php
Normal file
31
migrations/Version20221115104149.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20221115104149 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('ALTER TABLE user ADD tmp_avatar VARCHAR(255) DEFAULT NULL');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('ALTER TABLE user DROP tmp_avatar');
|
||||
}
|
||||
}
|
10
package.json
10
package.json
@ -1,11 +1,17 @@
|
||||
{
|
||||
"devDependencies": {
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"@hotwired/stimulus": "^3.0.0",
|
||||
"@hotwired/turbo": "^7.0.1",
|
||||
"@popperjs/core": "^2.11.6",
|
||||
"@symfony/stimulus-bridge": "^3.0.0",
|
||||
"@symfony/ux-cropperjs": "file:vendor/symfony/ux-cropperjs/Resources/assets",
|
||||
"@symfony/ux-dropzone": "file:vendor/symfony/ux-dropzone/Resources/assets",
|
||||
"@symfony/ux-turbo": "file:vendor/symfony/ux-turbo/Resources/assets",
|
||||
"@symfony/webpack-encore": "^2.0.0",
|
||||
"autoprefixer": "^10.4.7",
|
||||
"core-js": "^3.0.0",
|
||||
"cropperjs": "^1.5.9",
|
||||
"file-loader": "^6.0.0",
|
||||
"jquery": "^3.6.0",
|
||||
"less-loader": "^10.0.0",
|
||||
@ -13,6 +19,7 @@
|
||||
"regenerator-runtime": "^0.13.2",
|
||||
"sass": "^1.50.0",
|
||||
"sass-loader": "^12.0.0",
|
||||
"sweetalert2": "^11.6.8",
|
||||
"ts-loader": "^9.0.0",
|
||||
"typescript": "^4.6.4",
|
||||
"webpack-manifest-plugin": "^5.0.0",
|
||||
@ -44,6 +51,7 @@
|
||||
"postcss-import": "^14.1.0",
|
||||
"postcss-loader": "^7.0.0",
|
||||
"quill": "^1.3.7",
|
||||
"quill-html-edit-button": "^2.2.12"
|
||||
"quill-html-edit-button": "^2.2.12",
|
||||
"toastify-js": "^1.12.0"
|
||||
}
|
||||
}
|
||||
|
72
src/Command/CronRunCommand.php
Normal file
72
src/Command/CronRunCommand.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace App\Command;
|
||||
|
||||
use App\Repository\UserRepository;
|
||||
use Symfony\Component\Console\Attribute\AsCommand;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
|
||||
#[AsCommand(
|
||||
name: 'cron:run',
|
||||
description: 'Cleanup stale avatars',
|
||||
)]
|
||||
class CronRunCommand extends Command
|
||||
{
|
||||
public function __construct(private readonly UserRepository $userRepository)
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
/*
|
||||
$this
|
||||
->addArgument('arg1', InputArgument::OPTIONAL, 'Argument description')
|
||||
->addOption('option1', null, InputOption::VALUE_NONE, 'Option description')
|
||||
;
|
||||
*/
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
$verbose = $input->getOption('verbose');
|
||||
|
||||
$staleCount = $this->deleteStaleAvatars();
|
||||
|
||||
if ($verbose) {
|
||||
if ($staleCount > 0) {
|
||||
$io->writeln("There were " . $staleCount . " stale avatars.");
|
||||
} else {
|
||||
$io->writeln("There were no stale avatars younger than 24 hours.");
|
||||
}
|
||||
}
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
|
||||
private function deleteStaleAvatars(): int
|
||||
{
|
||||
$avatarDir = dirname(__DIR__, 2) . '/public/uploads/avatars';
|
||||
$keepTime = 86400; // 24 hours
|
||||
$deletedFiles = 0;
|
||||
|
||||
foreach (glob($avatarDir . '/*') as $entry) {
|
||||
$filectime = filectime($entry);
|
||||
if ($filectime && $filectime + $keepTime < time()) {
|
||||
// check if it in use
|
||||
if ($user = $this->userRepository->findOneBy(['avatar' => basename($entry)])) {
|
||||
echo basename($entry) . " is in use by: " . $user->getUserIdentifier() . PHP_EOL;
|
||||
}
|
||||
unlink($entry);
|
||||
$deletedFiles++;
|
||||
}
|
||||
|
||||
}
|
||||
return $deletedFiles;
|
||||
}
|
||||
}
|
@ -92,8 +92,8 @@ class SecurityController extends AbstractController
|
||||
return $this->render(view: '@default/security/registration_finished.html.twig');
|
||||
}
|
||||
|
||||
return $this->render(view: '@default/security/register.html.twig', parameters: [
|
||||
'registrationForm' => $form->createView(),
|
||||
return $this->renderForm(view: '@default/security/register.html.twig', parameters: [
|
||||
'registrationForm' => $form,
|
||||
]);
|
||||
}
|
||||
|
||||
@ -142,8 +142,8 @@ class SecurityController extends AbstractController
|
||||
);
|
||||
}
|
||||
|
||||
return $this->render(view: '@default/security/forgot_password.html.twig', parameters: [
|
||||
'requestForm' => $form->createView(),
|
||||
return $this->renderForm(view: '@default/security/forgot_password.html.twig', parameters: [
|
||||
'requestForm' => $form,
|
||||
]);
|
||||
}
|
||||
|
||||
@ -220,8 +220,8 @@ class SecurityController extends AbstractController
|
||||
return $this->redirectToRoute(route: 'app_main');
|
||||
}
|
||||
|
||||
return $this->render(view: '@default/security/reset_password.html.twig', parameters: [
|
||||
'resetForm' => $form->createView(),
|
||||
return $this->renderForm(view: '@default/security/reset_password.html.twig', parameters: [
|
||||
'resetForm' => $form,
|
||||
]);
|
||||
}
|
||||
|
||||
@ -330,7 +330,7 @@ class SecurityController extends AbstractController
|
||||
|
||||
|
||||
#[Route('/security/resend/verify_email', name: 'security_resend_verify_email')]
|
||||
public function resendVerifyEmail(Request $request, UserRepository $userRepository)
|
||||
public function resendVerifyEmail(Request $request, UserRepository $userRepository): Response
|
||||
{
|
||||
|
||||
if ($request->isMethod('POST')) {
|
||||
|
@ -6,6 +6,8 @@ use App\Entity\User;
|
||||
use App\Form\EditProfileFormType;
|
||||
use App\Repository\UserRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Flasher\Prime\FlasherInterface;
|
||||
use Flasher\SweetAlert\Prime\SweetAlertFactory;
|
||||
use Sunrise\Slugger\Slugger;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
@ -24,50 +26,6 @@ use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
*/
|
||||
class UserController extends BaseController
|
||||
{
|
||||
|
||||
#[Route(path: '/profile/edit/{username}', name: 'app_profile_edit')]
|
||||
public function editProfile(Request $request, UserRepository $userRepository, UserPasswordHasherInterface $userPasswordHasher, EntityManagerInterface $entityManager, string $username = ''): Response
|
||||
{
|
||||
if ($username !== '') {
|
||||
if ($this->isGranted(attribute: 'ROLE_ADMIN')) {
|
||||
$user = $userRepository->findOneBy([
|
||||
'username' => $username,
|
||||
]);
|
||||
} else {
|
||||
throw new AccessDeniedException(message: 'Only admins are allowed to edit foreign profiles.');
|
||||
}
|
||||
} else {
|
||||
$user = $this->getUser();
|
||||
}
|
||||
|
||||
$form = $this->createForm(type: EditProfileFormType::class, data: $user);
|
||||
$form->handleRequest(request: $request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$user = $form->getData();
|
||||
// if there's a new password, use it
|
||||
|
||||
if ($form->get(name: 'newPassword')->getData())
|
||||
$user->setPassword(
|
||||
password: $userPasswordHasher->hashPassword(
|
||||
user: $user,
|
||||
plainPassword: $form->get(name: 'newPassword')->getData()
|
||||
)
|
||||
);
|
||||
|
||||
$entityManager->persist(entity: $user);
|
||||
$entityManager->flush();
|
||||
|
||||
return $this->redirectToRoute(route: 'app_main');
|
||||
};
|
||||
|
||||
return $this->renderForm(view: '@default/user/edit_profile.html.twig', parameters: [
|
||||
'user' => $user,
|
||||
'userForm' => $form
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
#[Route(path: '/profile/{username}', name: 'app_profile')]
|
||||
public function showProfile(UserRepository $userRepository, string $username = ''): Response
|
||||
{
|
||||
@ -85,6 +43,61 @@ class UserController extends BaseController
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route(path: '/profile/edit/{username}', name: 'app_profile_edit')]
|
||||
public function editProfile(Request $request,
|
||||
UserRepository $userRepository,
|
||||
UserPasswordHasherInterface $userPasswordHasher,
|
||||
EntityManagerInterface $entityManager,
|
||||
string $username = ''): Response
|
||||
{
|
||||
$user = $this->getUser();
|
||||
|
||||
$editUser = $userRepository->findOneBy(['username' => $username]);
|
||||
|
||||
if ($username !== $editUser->getUsername()) {
|
||||
if (!$this->isGranted(attribute: 'ROLE_ADMIN')) {
|
||||
$this->addFlash(type: 'error', message: 'Only admins are allowed to edit foreign profiles.');
|
||||
return $this->redirectToRoute(route: 'app_main');
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$form = $this->createForm(type: EditProfileFormType::class, data: $user);
|
||||
$form->handleRequest(request: $request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$user = $form->getData();
|
||||
// if there's a new password, use it
|
||||
|
||||
if ($form->get(name: 'newPassword')->getData()) {
|
||||
$user->setPassword(
|
||||
password: $userPasswordHasher->hashPassword(
|
||||
user: $user,
|
||||
plainPassword: $form->get(name: 'newPassword')->getData()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ($user->getTmpAvatar()) {
|
||||
$user->setAvatar($user->getTmpAvatar());
|
||||
$user->setTmpAvatar('');
|
||||
}
|
||||
|
||||
$entityManager->persist(entity: $user);
|
||||
$entityManager->flush();
|
||||
|
||||
$this->addFlash(type: 'success', message: 'Profile successfully updated.');
|
||||
|
||||
return $this->redirectToRoute(route: 'app_main');
|
||||
};
|
||||
|
||||
return $this->renderForm(view: '@default/user/edit_profile.html.twig', parameters: [
|
||||
'user' => $editUser,
|
||||
'userForm' => $form
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
#[Route(path: '/list_users/', name: 'app_list_user')]
|
||||
public function listUsers(UserRepository $userRepository): Response
|
||||
{
|
||||
@ -96,7 +109,7 @@ class UserController extends BaseController
|
||||
}
|
||||
|
||||
// TODO move to a helper class
|
||||
function humanFilesize($bytes, $decimals = 2)
|
||||
function humanFilesize($bytes, $decimals = 2): string
|
||||
{
|
||||
$sz = 'BKMGTP';
|
||||
$factor = floor((strlen($bytes) - 1) / 3);
|
||||
@ -132,7 +145,8 @@ class UserController extends BaseController
|
||||
$cleanFilename = $slugger->slugify($originalFilename);
|
||||
$newFilename = $cleanFilename . '-' . uniqid() . '.' . $uploadedAvatar->guessExtension();
|
||||
$uploadedAvatar->move($destination, $newFilename);
|
||||
$user->setAvatar($newFilename);
|
||||
// Store the tmp name, use it on real form submit.
|
||||
$user->setTmpAvatar($newFilename);
|
||||
$entityManager->persist(entity: $user);
|
||||
$entityManager->flush();
|
||||
|
||||
|
@ -64,6 +64,9 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
|
||||
#[ORM\Column]
|
||||
private ?DateTimeImmutable $agreedTermsAt = null;
|
||||
|
||||
#[ORM\Column(length: 255, nullable: true)]
|
||||
private ?string $tmpAvatar = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->projects = new ArrayCollection();
|
||||
@ -315,4 +318,16 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
|
||||
{
|
||||
// TODO: Implement eraseCredentials() method.
|
||||
}
|
||||
|
||||
public function getTmpAvatar(): ?string
|
||||
{
|
||||
return $this->tmpAvatar;
|
||||
}
|
||||
|
||||
public function setTmpAvatar(?string $tmpAvatar): self
|
||||
{
|
||||
$this->tmpAvatar = $tmpAvatar;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -5,34 +5,65 @@ namespace App\Form;
|
||||
use App\Entity\User;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\EmailType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FileType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Validator\Constraints\Image;
|
||||
use Symfony\Component\Validator\Constraints\Length;
|
||||
use Symfony\UX\Cropperjs\Form\CropperType;
|
||||
use Symfony\UX\Dropzone\Form\DropzoneType;
|
||||
|
||||
class EditProfileFormType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
->add(child: 'username')
|
||||
->add(child: 'firstName')
|
||||
->add(child: 'lastName')
|
||||
->add(child: 'email', type: EmailType::class)
|
||||
->add(child: 'username', options: [
|
||||
'attr' => [
|
||||
'autocomplete' => 'nickname'
|
||||
]
|
||||
])
|
||||
->add(child: 'firstName', options: [
|
||||
'required' => false,
|
||||
'attr' => [
|
||||
'autocomplete' => 'given-name'
|
||||
]
|
||||
])
|
||||
->add(child: 'lastName', options: [
|
||||
'required' => false,
|
||||
'attr' => [
|
||||
'autocomplete' => 'family-name'
|
||||
]
|
||||
|
||||
])
|
||||
->add(child: 'email', type: EmailType::class, options: [
|
||||
'attr' => [
|
||||
'autocomplete' => 'email'
|
||||
]
|
||||
])
|
||||
/*
|
||||
->add(child: 'avatarName', type: DropzoneType::class, options: [
|
||||
'mapped' => false,
|
||||
'required' => false,
|
||||
'attr' => [
|
||||
'data-controller' => 'upload-avatar',
|
||||
]
|
||||
])
|
||||
*/
|
||||
->add(child: 'newPassword', type: RepeatedType::class, options: [
|
||||
'type' => PasswordType::class,
|
||||
'mapped' => false,
|
||||
'invalid_message' => 'The password fields must match.',
|
||||
'options' => ['attr' => ['class' => 'password-field', 'autocomplete' => 'off']],
|
||||
'required' => false,
|
||||
'first_options' => ['label' => 'Password'],
|
||||
'second_options' => ['label' => 'Repeat Password (only needed if you want to update the password)'],
|
||||
'constraints' => [new Length(exactly: ['min' => 6])]
|
||||
])
|
||||
;
|
||||
'constraints' => [new Length(exactly: ['min' => 6])],
|
||||
'options' => [
|
||||
'attr' => [
|
||||
'autocomplete' => 'new-password'
|
||||
]
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
|
15
symfony.lock
15
symfony.lock
@ -72,6 +72,12 @@
|
||||
"config/packages/nelmio_cors.yaml"
|
||||
]
|
||||
},
|
||||
"php-flasher/flasher-sweetalert-symfony": {
|
||||
"version": "v1.7.0"
|
||||
},
|
||||
"php-flasher/flasher-symfony": {
|
||||
"version": "v1.7.0"
|
||||
},
|
||||
"sensio/framework-extra-bundle": {
|
||||
"version": "6.2",
|
||||
"recipe": {
|
||||
@ -271,6 +277,15 @@
|
||||
"templates/base.html.twig"
|
||||
]
|
||||
},
|
||||
"symfony/ux-cropperjs": {
|
||||
"version": "v2.5.0"
|
||||
},
|
||||
"symfony/ux-dropzone": {
|
||||
"version": "v2.5.0"
|
||||
},
|
||||
"symfony/ux-turbo": {
|
||||
"version": "v2.5.0"
|
||||
},
|
||||
"symfony/validator": {
|
||||
"version": "6.1",
|
||||
"recipe": {
|
||||
|
@ -1,4 +1,6 @@
|
||||
<nav class="navbar navbar-expand-md navbar-dark bg-dark sticky-top px-sm-5 border-0">
|
||||
<nav
|
||||
class="navbar navbar-expand-md navbar-dark sticky-top px-sm-5 border-0 {{ is_granted('ROLE_PREVIOUS_ADMIN') ? 'bg-light' : 'bg-dark' }}"
|
||||
>
|
||||
|
||||
<a class="navbar-brand border-0" href="{{ path('app_main') }}">
|
||||
<img src="{{ asset('build/images/24unix/24_logo_bg_64x64.png') }}" alt="24unix.net" id="site-logo">
|
||||
@ -23,7 +25,7 @@
|
||||
<button type="button" id="navbar-dropdown" data-bs-target="#dropdown-menu" data-bs-toggle="dropdown"
|
||||
class="btn btn-outline-dark dropdown-toggle button-login">
|
||||
{% if app.user.avatar %}
|
||||
<img class="rounded-circle"
|
||||
<img class="rounded-circle border border-primary"
|
||||
width="50px"
|
||||
src="{{ avatar_asset(app.user.avatar)|imagine_filter('squared_thumbnail_small') }}"
|
||||
alt="profile image"/>
|
||||
@ -34,7 +36,7 @@
|
||||
|
||||
<div class="dropdown-menu dropdown-menu-dark dropdown-menu-end" id="dropdown-menu"
|
||||
aria-labelledby="navbar-dropdown">
|
||||
<a class="dropdown-item" href="{{ path('app_profile_edit') }}">
|
||||
<a class="dropdown-item" href="{{ path('app_profile_edit', { 'username': app.user.username }) }}">
|
||||
<span class="fa fa-lg fa-fw fa-user" aria-hidden="true"></span>
|
||||
Profile</a>
|
||||
<a class="dropdown-item" href="#">
|
||||
@ -49,6 +51,15 @@
|
||||
<div class="dropdown-divider"></div>
|
||||
{% endif %}
|
||||
|
||||
{% if is_granted('ROLE_PREVIOUS_ADMIN') %}
|
||||
<a class="dropdown-item" href="{{ path('app_main', {
|
||||
'_switch_user': '_exit'
|
||||
}) }}">
|
||||
<span class="fa fa-lg fa-fw fa-backward" aria-hidden="true"></span>
|
||||
Back to Admin</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
{% endif %}
|
||||
|
||||
<a class="dropdown-item" href="{{ path('security_logout') }}">
|
||||
<span class="fa fa-lg fa-fw fa-sign-out" aria-hidden="true"></span>
|
||||
Logout
|
@ -16,24 +16,25 @@
|
||||
|
||||
<!-- Matomo -->
|
||||
<script>
|
||||
let _paq = window._paq = window._paq || []
|
||||
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
|
||||
_paq.push(["trackPageView"])
|
||||
_paq.push(["enableLinkTracking"]);
|
||||
(function () {
|
||||
const u = "https://analytics.24unix.net/"
|
||||
_paq.push(["setTrackerUrl", u + "matomo.php"])
|
||||
_paq.push(["setSiteId", "1"])
|
||||
const d = document, g = d.createElement("script"), s = d.getElementsByTagName("script")[0]
|
||||
g.async = true
|
||||
g.src = u + "matomo.js"
|
||||
s.parentNode.insertBefore(g, s)
|
||||
})()
|
||||
let _paq = window._paq = window._paq || []
|
||||
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
|
||||
_paq.push(["trackPageView"])
|
||||
_paq.push(["enableLinkTracking"]);
|
||||
(function () {
|
||||
const u = "https://analytics.24unix.net/"
|
||||
_paq.push(["setTrackerUrl", u + "matomo.php"])
|
||||
_paq.push(["setSiteId", "1"])
|
||||
const d = document, g = d.createElement("script"), s = d.getElementsByTagName("script")[0]
|
||||
g.async = true
|
||||
g.src = u + "matomo.js"
|
||||
s.parentNode.insertBefore(g, s)
|
||||
})()
|
||||
</script>
|
||||
<!-- End Matomo Code -->
|
||||
{% endblock %}
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<body data-turbo="false">
|
||||
|
||||
{% include '@default/_header.html.twig' %}
|
||||
|
||||
@ -74,11 +75,20 @@
|
||||
|
||||
<div class="col m-3" id="main_content">
|
||||
|
||||
{% for message in app.flashes('success') %}
|
||||
<div class="alert alert-success">
|
||||
{{ message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{#
|
||||
<div data-turbo="false">
|
||||
{% for message in app.flashes('success') %}
|
||||
<div id="react"></div>
|
||||
<div
|
||||
{{ stimulus_controller('toastify', {
|
||||
flash: message
|
||||
}) }}
|
||||
>
|
||||
</div>
|
||||
dump(app)
|
||||
{% endfor %}
|
||||
</div>
|
||||
#}
|
||||
|
||||
{% for message in app.flashes('error') %}
|
||||
<div class="alert alert-danger">
|
||||
@ -101,5 +111,7 @@
|
||||
|
||||
{% include '@default/_footer.html.twig' %}
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
@ -10,4 +10,5 @@
|
||||
{% if page.modifiedAt %}
|
||||
(last update: {{ page.modifiedAt | ago }})
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
@ -20,12 +20,26 @@
|
||||
|
||||
<div class="col-12">
|
||||
<label for="inputUsername">Username or eMail</label>
|
||||
<input type="text" name="username" id="inputUsername"
|
||||
class="form-control" {# value="{{ last_username }}" #} required autofocus>
|
||||
<input type="text"
|
||||
name="username"
|
||||
autocomplete="nickname"
|
||||
id="inputUsername"
|
||||
class="form-control"
|
||||
value="{{ last_username }}"
|
||||
required
|
||||
autofocus
|
||||
>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label for="inputPassword">Password</label>
|
||||
<input type="password" name="password" id="inputPassword" class="form-control" required>
|
||||
<input
|
||||
type="password"
|
||||
name="password"
|
||||
autocomplete="current-password"
|
||||
id="inputPassword"
|
||||
class="form-control"
|
||||
required
|
||||
>
|
||||
</div>
|
||||
<div class="form-check mx-3">
|
||||
<label>
|
@ -7,25 +7,31 @@
|
||||
{% block body %}
|
||||
|
||||
<div class="container box rounded bg-dark mt-5 mb-5">
|
||||
|
||||
{{ form_start(userForm) }}
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-3 border-right">
|
||||
<div class="d-flex flex-column align-items-center text-center p-3 py-5">
|
||||
{#
|
||||
{% if user.avatar is not null %}
|
||||
<img class="rounded-circle mt-5 mb-4"
|
||||
src="{{ avatar_asset(user.avatar)|imagine_filter('squared_thumbnail_small') }}"
|
||||
alt="profile image"/>
|
||||
{% endif %}
|
||||
{# {{ form_row(userForm.avatarName, { 'label': false }) }} #}
|
||||
<form
|
||||
action="{{ path('user_upload_avatar', { id: user.id}) }}"
|
||||
method="POST"
|
||||
enctype="multipart/form-data"
|
||||
class="dropzone" id="dropzoneForm">
|
||||
</form>
|
||||
<div id="preview-content">{{ avatar_asset(user.avatar)|imagine_filter('squared_thumbnail_small') }}</div>
|
||||
#}
|
||||
|
||||
<div
|
||||
class="dropzone"
|
||||
id="avatarDropzone"
|
||||
style="width:172px;"
|
||||
{{ stimulus_controller('upload_avatar', {
|
||||
avatarImage: avatar_asset(user.avatar)|imagine_filter('squared_thumbnail_small') ,
|
||||
userId: user.id
|
||||
}) }}
|
||||
>
|
||||
</div>
|
||||
<span class="font-weight-bold">{{ user.username }}</span>
|
||||
<span class="text-white-50"><span class="fa fa-lg fa-envelope me-1"></span>{{ user.email }}</span>
|
||||
<span class="text-white-50"><span class="fa fa-lg fa-envelope me-1"></span><a href="mailto:{{ user.email }}">{{ user.email }}</a></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8 border-right">
|
||||
@ -34,7 +40,6 @@
|
||||
<h4 class="text-right">User Profile</h4>
|
||||
</div>
|
||||
<div class="row mt-2">
|
||||
{{ form_start(userForm) }}
|
||||
{{ form_row(userForm.username) }}
|
||||
{{ form_row(userForm.firstName) }}
|
||||
{{ form_row(userForm.lastName) }}
|
||||
@ -42,7 +47,6 @@
|
||||
{{ form_row(userForm.newPassword.first) }}
|
||||
{{ form_row(userForm.newPassword.second) }}
|
||||
{{ form_rest(userForm) }}
|
||||
{{ form_end(userForm) }}
|
||||
</div>
|
||||
<div class="mb-5 text-center float-end">
|
||||
<button class="btn btn-primary profile-button" type="submit">Save Profile</button>
|
||||
@ -50,6 +54,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ form_end(userForm) }}
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
46
templates/themes/24unix.net/user/show_profile.html.twig
Normal file
46
templates/themes/24unix.net/user/show_profile.html.twig
Normal file
@ -0,0 +1,46 @@
|
||||
{% extends '@default/base.html.twig' %}
|
||||
|
||||
{% block title %}
|
||||
Profile of {{ user.username }}
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
<div class="container box rounded bg-dark mt-5 mb-5">
|
||||
<div class="row">
|
||||
<div class="col-md-3 border-right">
|
||||
<div class="d-flex flex-column align-items-center text-center p-3 py-5">
|
||||
{% if user.avatar is not null %}
|
||||
<img class="rounded-circle mt-5 mb-4"
|
||||
src="{{ avatar_asset(user.avatar)|imagine_filter('squared_thumbnail_small') }}"
|
||||
alt="profile image"/>
|
||||
{% endif %}
|
||||
<span class="font-weight-bold">{{ user.username }}</span>
|
||||
{% if is_granted('ROLE_ADMIN') %}
|
||||
<span class="font-weight-bold">
|
||||
<a href="{{ path('app_main', { '_switch_user': user.username }) }}">switch user</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
<span class="text-white-50"><i class="fa fa-lg fa-envelope me-1"></i><a href="mailto:{{ user.email }}">{{ user.email }}</a></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-5 border-right">
|
||||
<div class="p-3 py-5">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h4 class="text-right">User Profile</h4>
|
||||
</div>
|
||||
<div class="row mt-2">
|
||||
<label class="labels" for="first-name">First Name</label>
|
||||
<input type="text" disabled id="first-name" class="form-control" value="{{ user.firstName }}">
|
||||
|
||||
<label class="labels" for="last-name">Last Name</label>
|
||||
<input type="text" disabled id="last-name" class="form-control" value="{{ user.lastName }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% endblock %}
|
1
templates/themes/default
Symbolic link
1
templates/themes/default
Symbolic link
@ -0,0 +1 @@
|
||||
24unix.net
|
@ -1,63 +0,0 @@
|
||||
{% extends '@default/base.html.twig' %}
|
||||
|
||||
{% block title %}
|
||||
Profile of {{ user.username }}
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
<div class="container box rounded bg-dark mt-5 mb-5">
|
||||
<div class="row">
|
||||
<div class="col-md-3 border-right">
|
||||
<div class="d-flex flex-column align-items-center text-center p-3 py-5">
|
||||
{% if user.avatar is not null %}
|
||||
<img class="rounded-circle mt-5 mb-4"
|
||||
src="{{ avatar_asset(user.avatar)|imagine_filter('squared_thumbnail_small') }}" alt="profile image"/>
|
||||
{% endif %}
|
||||
<span class="font-weight-bold">{{ user.username }}</span>
|
||||
{% if is_granted('ROLE_ADMIN') %}
|
||||
<span class="font-weight-bold">
|
||||
<a href="{{ path('app_main', { '_switch_user': app.user.username }) }}">switch user {{ user.username }}</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
<span class="text-white-50"><i class="fa fa-lg fa-envelope me-1"></i>{{ user.email }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-5 border-right">
|
||||
<div class="p-3 py-5">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h4 class="text-right">User Profile</h4>
|
||||
</div>
|
||||
<div class="row mt-2">
|
||||
<div class="col-md-6">
|
||||
<label class="labels" for="first-name">First Name</label>
|
||||
<input type="text" disabled id="first-name" class="form-control" placeholder="First Name"
|
||||
value="{{ user.firstName }}">
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="labels" for="last-name">Last Name</label>
|
||||
<input type="text" disabled id="last-name" class="form-control" value="{{ user.lastName }}"
|
||||
placeholder="Last Name">
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="labels" for="username">Username</label>
|
||||
<input type="text" disabled class="form-control" id="username" placeholder="eMail address"
|
||||
value="{{ user.email }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<div class="mt-5 text-center">
|
||||
<button class="btn btn-primary profile-button" type="button">Save Profile</button>
|
||||
</div>
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% endblock %}
|
@ -43,5 +43,9 @@ Encore
|
||||
}
|
||||
})
|
||||
.autoProvidejQuery()
|
||||
.enableStimulusBridge(
|
||||
'./assets/controllers.json'
|
||||
)
|
||||
.enableReactPreset()
|
||||
|
||||
module.exports = Encore.getWebpackConfig()
|
||||
|
81
yarn.lock
81
yarn.lock
@ -461,6 +461,13 @@
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.8.0"
|
||||
|
||||
"@babel/plugin-syntax-jsx@^7.18.6":
|
||||
version "7.18.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0"
|
||||
integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.18.6"
|
||||
|
||||
"@babel/plugin-syntax-logical-assignment-operators@^7.10.4":
|
||||
version "7.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699"
|
||||
@ -701,6 +708,39 @@
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.18.6"
|
||||
|
||||
"@babel/plugin-transform-react-display-name@^7.18.6":
|
||||
version "7.18.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz#8b1125f919ef36ebdfff061d664e266c666b9415"
|
||||
integrity sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.18.6"
|
||||
|
||||
"@babel/plugin-transform-react-jsx-development@^7.18.6":
|
||||
version "7.18.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz#dbe5c972811e49c7405b630e4d0d2e1380c0ddc5"
|
||||
integrity sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==
|
||||
dependencies:
|
||||
"@babel/plugin-transform-react-jsx" "^7.18.6"
|
||||
|
||||
"@babel/plugin-transform-react-jsx@^7.18.6":
|
||||
version "7.19.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.19.0.tgz#b3cbb7c3a00b92ec8ae1027910e331ba5c500eb9"
|
||||
integrity sha512-UVEvX3tXie3Szm3emi1+G63jyw1w5IcMY0FSKM+CRnKRI5Mr1YbCNgsSTwoTwKphQEG9P+QqmuRFneJPZuHNhg==
|
||||
dependencies:
|
||||
"@babel/helper-annotate-as-pure" "^7.18.6"
|
||||
"@babel/helper-module-imports" "^7.18.6"
|
||||
"@babel/helper-plugin-utils" "^7.19.0"
|
||||
"@babel/plugin-syntax-jsx" "^7.18.6"
|
||||
"@babel/types" "^7.19.0"
|
||||
|
||||
"@babel/plugin-transform-react-pure-annotations@^7.18.6":
|
||||
version "7.18.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz#561af267f19f3e5d59291f9950fd7b9663d0d844"
|
||||
integrity sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ==
|
||||
dependencies:
|
||||
"@babel/helper-annotate-as-pure" "^7.18.6"
|
||||
"@babel/helper-plugin-utils" "^7.18.6"
|
||||
|
||||
"@babel/plugin-transform-regenerator@^7.18.6":
|
||||
version "7.18.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz#585c66cb84d4b4bf72519a34cfce761b8676ca73"
|
||||
@ -859,6 +899,18 @@
|
||||
"@babel/types" "^7.4.4"
|
||||
esutils "^2.0.2"
|
||||
|
||||
"@babel/preset-react@^7.0.0":
|
||||
version "7.18.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.18.6.tgz#979f76d6277048dc19094c217b507f3ad517dd2d"
|
||||
integrity sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.18.6"
|
||||
"@babel/helper-validator-option" "^7.18.6"
|
||||
"@babel/plugin-transform-react-display-name" "^7.18.6"
|
||||
"@babel/plugin-transform-react-jsx" "^7.18.6"
|
||||
"@babel/plugin-transform-react-jsx-development" "^7.18.6"
|
||||
"@babel/plugin-transform-react-pure-annotations" "^7.18.6"
|
||||
|
||||
"@babel/runtime@^7.8.4":
|
||||
version "7.20.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.1.tgz#1148bb33ab252b165a06698fde7576092a78b4a9"
|
||||
@ -935,6 +987,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@hotwired/stimulus/-/stimulus-3.1.1.tgz#652f08a8e1d5edcb407340e58818fcff463b5848"
|
||||
integrity sha512-e0JpzIaYLsRRXevRDVs0yevabiCvieIWWCwh7VqVXjXM5AOHdjb7AjaKIj34zYFmY1N6HIRRfk915WVMYlHnDA==
|
||||
|
||||
"@hotwired/turbo@^7.0.1":
|
||||
version "7.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@hotwired/turbo/-/turbo-7.2.4.tgz#0d35541be32cfae3b4f78c6ab9138f5b21f28a21"
|
||||
integrity sha512-c3xlOroHp/cCZHDOuLp6uzQYEbvXBUVaal0puXoGJ9M8L/KHwZ3hQozD4dVeSN9msHWLxxtmPT1TlCN7gFhj4w==
|
||||
|
||||
"@humanwhocodes/config-array@^0.11.6":
|
||||
version "0.11.7"
|
||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.7.tgz#38aec044c6c828f6ed51d5d7ae3d9b9faf6dbb0f"
|
||||
@ -1059,6 +1116,15 @@
|
||||
loader-utils "^2.0.0"
|
||||
schema-utils "^3.0.0"
|
||||
|
||||
"@symfony/ux-cropperjs@file:vendor/symfony/ux-cropperjs/Resources/assets":
|
||||
version "1.1.0"
|
||||
|
||||
"@symfony/ux-dropzone@file:vendor/symfony/ux-dropzone/Resources/assets":
|
||||
version "1.1.0"
|
||||
|
||||
"@symfony/ux-turbo@file:vendor/symfony/ux-turbo/Resources/assets":
|
||||
version "0.1.0"
|
||||
|
||||
"@symfony/webpack-encore@^2.0.0":
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@symfony/webpack-encore/-/webpack-encore-2.1.0.tgz#353a1b8bc38022046cbbc3d627c4076aca2e28c3"
|
||||
@ -2042,6 +2108,11 @@ cosmiconfig@^7.0.0:
|
||||
path-type "^4.0.0"
|
||||
yaml "^1.10.0"
|
||||
|
||||
cropperjs@^1.5.9:
|
||||
version "1.5.12"
|
||||
resolved "https://registry.yarnpkg.com/cropperjs/-/cropperjs-1.5.12.tgz#d9c0db2bfb8c0d769d51739e8f916bbc44e10f50"
|
||||
integrity sha512-re7UdjE5UnwdrovyhNzZ6gathI4Rs3KGCBSc8HCIjUo5hO42CtzyblmWLj6QWVw7huHyDMfpKxhiO2II77nhDw==
|
||||
|
||||
cross-spawn@^7.0.2, cross-spawn@^7.0.3:
|
||||
version "7.0.3"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
|
||||
@ -5111,6 +5182,11 @@ svgo@^2.7.0:
|
||||
picocolors "^1.0.0"
|
||||
stable "^0.1.8"
|
||||
|
||||
sweetalert2@^11.6.8:
|
||||
version "11.6.8"
|
||||
resolved "https://registry.yarnpkg.com/sweetalert2/-/sweetalert2-11.6.8.tgz#5a515284367bc21b9f7830cbfbbfd09341576cca"
|
||||
integrity sha512-0YHMaqF3DC67EI9uZzHpbU34rQV3acEFlnUCYmDSDNkeNOSFtSlF4DbWilfln+iUYv9s9aqbREXmKZRJqh5G5w==
|
||||
|
||||
sync-rpc@^1.3.6:
|
||||
version "1.3.6"
|
||||
resolved "https://registry.yarnpkg.com/sync-rpc/-/sync-rpc-1.3.6.tgz#b2e8b2550a12ccbc71df8644810529deb68665a7"
|
||||
@ -5173,6 +5249,11 @@ to-regex-range@^5.0.1:
|
||||
dependencies:
|
||||
is-number "^7.0.0"
|
||||
|
||||
toastify-js@^1.12.0:
|
||||
version "1.12.0"
|
||||
resolved "https://registry.yarnpkg.com/toastify-js/-/toastify-js-1.12.0.tgz#cc1c4f5c7e7380e854e20bedceb51980ea29f64d"
|
||||
integrity sha512-HeMHCO9yLPvP9k0apGSdPUWrUbLnxUKNFzgUoZp1PHCLploIX/4DSQ7V8H25ef+h4iO9n0he7ImfcndnN6nDrQ==
|
||||
|
||||
toidentifier@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
|
||||
|
Loading…
Reference in New Issue
Block a user