Quote of the Moment
++ {{ quote | raw | nl2br }} +
diff --git a/assets/controllers/crop_avatar_controller.js b/assets/controllers/crop_avatar_controller.js new file mode 100644 index 0000000..2393657 --- /dev/null +++ b/assets/controllers/crop_avatar_controller.js @@ -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', + ) + } + }) + } +} diff --git a/assets/controllers/hello_controller.js b/assets/controllers/hello_controller.js deleted file mode 100644 index e847027..0000000 --- a/assets/controllers/hello_controller.js +++ /dev/null @@ -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'; - } -} diff --git a/assets/controllers/upload-avatar_controller.js b/assets/controllers/upload-avatar_controller.js new file mode 100644 index 0000000..96d9dd3 --- /dev/null +++ b/assets/controllers/upload-avatar_controller.js @@ -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) + } + }) + } +} diff --git a/templates/themes/24unix.net/_footer.html.twig b/templates/themes/24unix.net/_footer.html.twig new file mode 100644 index 0000000..a7208df --- /dev/null +++ b/templates/themes/24unix.net/_footer.html.twig @@ -0,0 +1,15 @@ + \ No newline at end of file diff --git a/templates/themes/24unix.net/_header.html.twig b/templates/themes/24unix.net/_header.html.twig new file mode 100644 index 0000000..b99ea83 --- /dev/null +++ b/templates/themes/24unix.net/_header.html.twig @@ -0,0 +1,79 @@ + diff --git a/templates/themes/24unix.net/base.html.twig b/templates/themes/24unix.net/base.html.twig new file mode 100644 index 0000000..9110af2 --- /dev/null +++ b/templates/themes/24unix.net/base.html.twig @@ -0,0 +1,117 @@ + + +
+ + +To reset your password, please visit the following link
+ +Reset password + +This link will expire in {{ resetToken.expirationMessageKey|trans(resetToken.expirationMessageData, 'ResetPasswordBundle') }}.
+ +Cheers!
diff --git a/templates/themes/24unix.net/security/mail/registration.html.twig b/templates/themes/24unix.net/security/mail/registration.html.twig new file mode 100644 index 0000000..665506f --- /dev/null +++ b/templates/themes/24unix.net/security/mail/registration.html.twig @@ -0,0 +1,39 @@ + + + + + + + +
+ Please confirm your email address by clicking the following link:
+ Confirm my Email.
+
+ This link will expire in {{ expiresAtMessageKey|trans(expiresAtMessageData, 'VerifyEmailBundle') }}.
+
+ Kind regards, + 24unix.net +
++ If an account matching your email exists, then an email was just sent that contains a link that you can use to reset your password. + This link will expire in {{ resetToken.expirationMessageKey|trans(resetToken.expirationMessageData, 'ResetPasswordBundle') }}. +
+If you don't receive an email please check your spam folder or try again.
+{% endblock %} diff --git a/templates/themes/24unix.net/security/register.html.twig b/templates/themes/24unix.net/security/register.html.twig new file mode 100644 index 0000000..6b3a3bc --- /dev/null +++ b/templates/themes/24unix.net/security/register.html.twig @@ -0,0 +1,60 @@ +{% extends '@default/base.html.twig' %} +{% form_theme registrationForm _self %} + +{% block title %}Register{% endblock %} + + +{% block form_row %} + {%- set widget_attr = {} -%} + {%- if help is not empty -%} + {%- set widget_attr = {attr: {'aria-describedby': id ~"_help"}} -%} + {%- endif -%} + + {{- form_label(form, null, { + label_attr: { class: 'sr-only' } + }) -}} + {{- form_errors(form) -}} + {{- form_widget(form, widget_attr) -}} + {{- form_help(form) -}} +{% endblock %} + + +{% block body %} + {% for flash_error in app.flashes('verify_email_error') %} +You'll receive an email soon to confirm your identity.
+ ++ A verification email was sent - please check it to enable your + account before logging in. +
+ +Username | +First | +Last | +Registered | +Manage | +|
---|---|---|---|---|---|
+ {{ user.username }} + | ++ {{ user.firstName }} + | ++ {{ user.lastName }} + | ++ {{ user.email }} + | ++ {{ user.createdAt|ago }} + | ++ + | + +