symlinked default
This commit is contained in:
assets/controllers
templates/themes/24unix.net
34
assets/controllers/crop_avatar_controller.js
Normal file
34
assets/controllers/crop_avatar_controller.js
Normal file
@ -0,0 +1,34 @@
|
||||
import { Controller } from '@hotwired/stimulus'
|
||||
import Swal from 'sweetalert2'
|
||||
|
||||
export default class extends Controller {
|
||||
static values = {
|
||||
cropImage: String
|
||||
}
|
||||
|
||||
connect() {
|
||||
console.log('crop', this.cropImageValue)
|
||||
window.CropAvatar = this
|
||||
}
|
||||
|
||||
open() {
|
||||
console.log('open crop')
|
||||
Swal.fire({
|
||||
title: 'Are you sure?',
|
||||
text: "You won't be able to revert this!",
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonColor: '#3085d6',
|
||||
cancelButtonColor: '#d33',
|
||||
confirmButtonText: 'Yes, delete it!',
|
||||
}).then((result) => {
|
||||
if (result.isConfirmed) {
|
||||
Swal.fire(
|
||||
'Deleted!',
|
||||
'Your file has been deleted.',
|
||||
'success',
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -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';
|
||||
}
|
||||
}
|
158
assets/controllers/upload-avatar_controller.js
Normal file
158
assets/controllers/upload-avatar_controller.js
Normal file
@ -0,0 +1,158 @@
|
||||
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() {
|
||||
console.log('image', this.avatarImageValue)
|
||||
console.log('id', this.userIdValue)
|
||||
|
||||
/*
|
||||
const formElement = document.getElementById('avatarDropzone')
|
||||
const dzMessage = document.getElementsByClassName('dz-message')
|
||||
formElement.style.backgroundImage = `url('${this.avatarImageValue}')`
|
||||
formElement.style.backgroundRepeat = 'no-repeat'
|
||||
formElement.style.backgroundPosition = 'center center'
|
||||
formElement.style.backgroundSize = 'auto'
|
||||
formElement.style.borderRadius = '25px'
|
||||
console.log('formelement', formElement)
|
||||
*/
|
||||
|
||||
console.log('init Dropzone')
|
||||
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
|
||||
|
||||
/*
|
||||
console.log('url', avatarDropzone.options.foo)
|
||||
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('beforemock')
|
||||
const mockFile = { name: 'Name Image', size: 12345, type: 'image/jpeg' }
|
||||
this.emit('addedfile', mockFile)
|
||||
this.emit('success', mockFile)
|
||||
console.log('avi', this.avatarImageValue)
|
||||
this.emit('thumbnail', mockFile, avatarDropzone.options.avatarUrl)
|
||||
console.log('aftermock')
|
||||
this.emit('complete', mockFile);
|
||||
this.files.push(mockFile);
|
||||
*/
|
||||
},
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user