diff --git a/config/services.yaml b/config/services.yaml index fc181e9..7613ecd 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -30,4 +30,4 @@ services: tags: - name: "doctrine.event_listener" event: "postPersist" - entity: 'App\Entity\Company' + entity: 'App\Entity\Company' \ No newline at end of file diff --git a/public/lib/app/app.css b/public/lib/app/app.css index f3a38b4..f405871 100644 --- a/public/lib/app/app.css +++ b/public/lib/app/app.css @@ -11,8 +11,14 @@ body { .avatar{ border-radius: 100%; - width:40px; - height:40px; + width:35px; + height:35px; +} + +.bigavatar{ + border-radius: 100%; + width:100px; + height:100px; } .navbar-brand img { diff --git a/public/lib/app/app.js b/public/lib/app/app.js index 3903a29..32399ce 100644 --- a/public/lib/app/app.js +++ b/public/lib/app/app.js @@ -2,3 +2,22 @@ function ModalLoad(idmodal,title,path) { $("#"+idmodal+" .modal-header h4").text(title); $("#"+idmodal+" #framemodal").attr("src",path); } + +$(document).ready(function(){ + + $("#selectcompany").on("change", function() { + url=$(this).data("change"); + + $.ajax({ + type: "POST", + url: url, + data: { + id: $(this).val() + }, + success: function (result) { + location.reload(); + } + }); + + }); +}); diff --git a/public/lib/fontawesome/FontAwesome-v5.0.9-Free.json b/public/lib/fontawesome/FontAwesome-v5.0.9-Free.json new file mode 100644 index 0000000..462d02f --- /dev/null +++ b/public/lib/fontawesome/FontAwesome-v5.0.9-Free.json @@ -0,0 +1,3 @@ +{ + "fas fa-address-book","fas fa-address-card","fas fa-adjust","fas fa-align-center","fas fa-align-justify","fas fa-align-left","fas fa-align-right","fas fa-allergies","fas fa-ambulance","fas fa-american-sign-language-interpreting","fas fa-anchor","fas fa-angle-double-down","fas fa-angle-double-left","fas fa-angle-double-right","fas fa-angle-double-up","fas fa-angle-down","fas fa-angle-left","fas fa-angle-right","fas fa-angle-up","fas fa-archive","fas fa-arrow-alt-circle-down","fas fa-arrow-alt-circle-left","fas fa-arrow-alt-circle-right","fas fa-arrow-alt-circle-up","fas fa-arrow-circle-down","fas fa-arrow-circle-left","fas fa-arrow-circle-right","fas fa-arrow-circle-up","fas fa-arrow-down","fas fa-arrow-left","fas fa-arrow-right","fas fa-arrow-up","fas fa-arrows-alt","fas fa-arrows-alt-h","fas fa-arrows-alt-v","fas fa-assistive-listening-systems","fas fa-asterisk","fas fa-at","fas fa-audio-description","fas fa-backward","fas fa-balance-scale","fas fa-ban","fas fa-band-aid","fas fa-barcode","fas fa-bars","fas fa-baseball-ball","fas fa-basketball-ball","fas fa-bath","fas fa-battery-empty","fas fa-battery-full","fas fa-battery-half","fas fa-battery-quarter","fas fa-battery-three-quarters","fas fa-bed","fas fa-beer","fas fa-bell","fas fa-bell-slash","fas fa-bicycle","fas fa-binoculars","fas fa-birthday-cake","fas fa-blind","fas fa-bold","fas fa-bolt","fas fa-bomb","fas fa-book","fas fa-bookmark","fas fa-bowling-ball","fas fa-box","fas fa-box-open","fas fa-boxes","fas fa-braille","fas fa-briefcase","fas fa-briefcase-medical","fas fa-bug","fas fa-building","fas fa-bullhorn","fas fa-bullseye","fas fa-burn","fas fa-bus","fas fa-calculator","fas fa-calendar","fas fa-calendar-alt","fas fa-calendar-check","fas fa-calendar-minus","fas fa-calendar-plus","fas fa-calendar-times","fas fa-camera","fas fa-camera-retro","fas fa-capsules","fas fa-car","fas fa-caret-down","fas fa-caret-left","fas fa-caret-right","fas fa-caret-square-down","fas fa-caret-square-left","fas fa-caret-square-right","fas fa-caret-square-up","fas fa-caret-up","fas fa-cart-arrow-down","fas fa-cart-plus","fas fa-certificate","fas fa-chart-area","fas fa-chart-bar","fas fa-chart-line","fas fa-chart-pie","fas fa-check","fas fa-check-circle","fas fa-check-square","fas fa-chess","fas fa-chess-bishop","fas fa-chess-board","fas fa-chess-king","fas fa-chess-knight","fas fa-chess-pawn","fas fa-chess-queen","fas fa-chess-rook","fas fa-chevron-circle-down","fas fa-chevron-circle-left","fas fa-chevron-circle-right","fas fa-chevron-circle-up","fas fa-chevron-down","fas fa-chevron-left","fas fa-chevron-right","fas fa-chevron-up","fas fa-child","fas fa-circle","fas fa-circle-notch","fas fa-clipboard","fas fa-clipboard-check","fas fa-clipboard-list","fas fa-clock","fas fa-clone","fas fa-closed-captioning","fas fa-cloud","fas fa-cloud-download-alt","fas fa-cloud-upload-alt","fas fa-code","fas fa-code-branch","fas fa-coffee","fas fa-cog","fas fa-cogs","fas fa-columns","fas fa-comment","fas fa-comment-alt","fas fa-comment-dots","fas fa-comment-slash","fas fa-comments","fas fa-compass","fas fa-compress","fas fa-copy","fas fa-copyright","fas fa-couch","fas fa-credit-card","fas fa-crop","fas fa-crosshairs","fas fa-cube","fas fa-cubes","fas fa-cut","fas fa-database","fas fa-deaf","fas fa-desktop","fas fa-diagnoses","fas fa-dna","fas fa-dollar-sign","fas fa-dolly","fas fa-dolly-flatbed","fas fa-donate","fas fa-dot-circle","fas fa-dove","fas fa-download","fas fa-edit","fas fa-eject","fas fa-ellipsis-h","fas fa-ellipsis-v","fas fa-envelope","fas fa-envelope-open","fas fa-envelope-square","fas fa-eraser","fas fa-euro-sign","fas fa-exchange-alt","fas fa-exclamation","fas fa-exclamation-circle","fas fa-exclamation-triangle","fas fa-expand","fas fa-expand-arrows-alt","fas fa-external-link-alt","fas fa-external-link-square-alt","fas fa-eye","fas fa-eye-dropper","fas fa-eye-slash","fas fa-fast-backward","fas fa-fast-forward","fas fa-fax","fas fa-female","fas fa-fighter-jet","fas fa-file","fas fa-file-alt","fas fa-file-archive","fas fa-file-audio","fas fa-file-code","fas fa-file-excel","fas fa-file-image","fas fa-file-medical","fas fa-file-medical-alt","fas fa-file-pdf","fas fa-file-powerpoint","fas fa-file-video","fas fa-file-word","fas fa-film","fas fa-filter","fas fa-fire","fas fa-fire-extinguisher","fas fa-first-aid","fas fa-flag","fas fa-flag-checkered","fas fa-flask","fas fa-folder","fas fa-folder-open","fas fa-font","fas fa-football-ball","fas fa-forward","fas fa-frown","fas fa-futbol","fas fa-gamepad","fas fa-gavel","fas fa-gem","fas fa-genderless","fas fa-gift","fas fa-glass-martini","fas fa-globe","fas fa-golf-ball","fas fa-graduation-cap","fas fa-h-square","fas fa-hand-holding","fas fa-hand-holding-heart","fas fa-hand-holding-usd","fas fa-hand-lizard","fas fa-hand-paper","fas fa-hand-peace","fas fa-hand-point-down","fas fa-hand-point-left","fas fa-hand-point-right","fas fa-hand-point-up","fas fa-hand-pointer","fas fa-hand-rock","fas fa-hand-scissors","fas fa-hand-spock","fas fa-hands","fas fa-hands-helping","fas fa-handshake","fas fa-hashtag","fas fa-hdd","fas fa-heading","fas fa-headphones","fas fa-heart","fas fa-heartbeat","fas fa-history","fas fa-hockey-puck","fas fa-home","fas fa-hospital","fas fa-hospital-alt","fas fa-hospital-symbol","fas fa-hourglass","fas fa-hourglass-end","fas fa-hourglass-half","fas fa-hourglass-start","fas fa-i-cursor","fas fa-id-badge","fas fa-id-card","fas fa-id-card-alt","fas fa-image","fas fa-images","fas fa-inbox","fas fa-indent","fas fa-industry","fas fa-info","fas fa-info-circle","fas fa-italic","fas fa-key","fas fa-keyboard","fas fa-language","fas fa-laptop","fas fa-leaf","fas fa-lemon","fas fa-level-down-alt","fas fa-level-up-alt","fas fa-life-ring","fas fa-lightbulb","fas fa-link","fas fa-lira-sign","fas fa-list","fas fa-list-alt","fas fa-list-ol","fas fa-list-ul","fas fa-location-arrow","fas fa-lock","fas fa-lock-open","fas fa-long-arrow-alt-down","fas fa-long-arrow-alt-left","fas fa-long-arrow-alt-right","fas fa-long-arrow-alt-up","fas fa-low-vision","fas fa-magic","fas fa-magnet","fas fa-male","fas fa-map","fas fa-map-marker","fas fa-map-marker-alt","fas fa-map-pin","fas fa-map-signs","fas fa-mars","fas fa-mars-double","fas fa-mars-stroke","fas fa-mars-stroke-h","fas fa-mars-stroke-v","fas fa-medkit","fas fa-meh","fas fa-mercury","fas fa-microchip","fas fa-microphone","fas fa-microphone-slash","fas fa-minus","fas fa-minus-circle","fas fa-minus-square","fas fa-mobile","fas fa-mobile-alt","fas fa-money-bill-alt","fas fa-moon","fas fa-motorcycle","fas fa-mouse-pointer","fas fa-music","fas fa-neuter","fas fa-newspaper","fas fa-notes-medical","fas fa-object-group","fas fa-object-ungroup","fas fa-outdent","fas fa-paint-brush","fas fa-pallet","fas fa-paper-plane","fas fa-paperclip","fas fa-parachute-box","fas fa-paragraph","fas fa-paste","fas fa-pause","fas fa-pause-circle","fas fa-paw","fas fa-pen-square","fas fa-pencil-alt","fas fa-people-carry","fas fa-percent","fas fa-phone","fas fa-phone-slash","fas fa-phone-square","fas fa-phone-volume","fas fa-piggy-bank","fas fa-pills","fas fa-plane","fas fa-play","fas fa-play-circle","fas fa-plug","fas fa-plus","fas fa-plus-circle","fas fa-plus-square","fas fa-podcast","fas fa-poo","fas fa-pound-sign","fas fa-power-off","fas fa-prescription-bottle","fas fa-prescription-bottle-alt","fas fa-print","fas fa-procedures","fas fa-puzzle-piece","fas fa-qrcode","fas fa-question","fas fa-question-circle","fas fa-quidditch","fas fa-quote-left","fas fa-quote-right","fas fa-random","fas fa-recycle","fas fa-redo","fas fa-redo-alt","fas fa-registered","fas fa-reply","fas fa-reply-all","fas fa-retweet","fas fa-ribbon","fas fa-road","fas fa-rocket","fas fa-rss","fas fa-rss-square","fas fa-ruble-sign","fas fa-rupee-sign","fas fa-save","fas fa-search","fas fa-search-minus","fas fa-search-plus","fas fa-seedling","fas fa-server","fas fa-share","fas fa-share-alt","fas fa-share-alt-square","fas fa-share-square","fas fa-shekel-sign","fas fa-shield-alt","fas fa-ship","fas fa-shipping-fast","fas fa-shopping-bag","fas fa-shopping-basket","fas fa-shopping-cart","fas fa-shower","fas fa-sign","fas fa-sign-in-alt","fas fa-sign-language","fas fa-sign-out-alt","fas fa-signal","fas fa-sitemap","fas fa-sliders-h","fas fa-smile","fas fa-smoking","fas fa-snowflake","fas fa-sort","fas fa-sort-alpha-down","fas fa-sort-alpha-up","fas fa-sort-amount-down","fas fa-sort-amount-up","fas fa-sort-down","fas fa-sort-numeric-down","fas fa-sort-numeric-up","fas fa-sort-up","fas fa-space-shuttle","fas fa-spinner","fas fa-square","fas fa-square-full","fas fa-star","fas fa-star-half","fas fa-step-backward","fas fa-step-forward","fas fa-stethoscope","fas fa-sticky-note","fas fa-stop","fas fa-stop-circle","fas fa-stopwatch","fas fa-street-view","fas fa-strikethrough","fas fa-subscript","fas fa-subway","fas fa-suitcase","fas fa-sun","fas fa-superscript","fas fa-sync","fas fa-sync-alt","fas fa-syringe","fas fa-table","fas fa-table-tennis","fas fa-tablet","fas fa-tablet-alt","fas fa-tablets","fas fa-tachometer-alt","fas fa-tag","fas fa-tags","fas fa-tape","fas fa-tasks","fas fa-taxi","fas fa-terminal","fas fa-text-height","fas fa-text-width","fas fa-th","fas fa-th-large","fas fa-th-list","fas fa-thermometer","fas fa-thermometer-empty","fas fa-thermometer-full","fas fa-thermometer-half","fas fa-thermometer-quarter","fas fa-thermometer-three-quarters","fas fa-thumbs-down","fas fa-thumbs-up","fas fa-thumbtack","fas fa-ticket-alt","fas fa-times","fas fa-times-circle","fas fa-tint","fas fa-toggle-off","fas fa-toggle-on","fas fa-trademark","fas fa-train","fas fa-transgender","fas fa-transgender-alt","fas fa-trash","fas fa-trash-alt","fas fa-tree","fas fa-trophy","fas fa-truck","fas fa-truck-loading","fas fa-truck-moving","fas fa-tty","fas fa-tv","fas fa-umbrella","fas fa-underline","fas fa-undo","fas fa-undo-alt","fas fa-universal-access","fas fa-university","fas fa-unlink","fas fa-unlock","fas fa-unlock-alt","fas fa-upload","fas fa-user","fas fa-user-circle","fas fa-user-md","fas fa-user-plus","fas fa-user-secret","fas fa-user-times","fas fa-users","fas fa-utensil-spoon","fas fa-utensils","fas fa-venus","fas fa-venus-double","fas fa-venus-mars","fas fa-vial","fas fa-vials","fas fa-video","fas fa-video-slash","fas fa-volleyball-ball","fas fa-volume-down","fas fa-volume-off","fas fa-volume-up","fas fa-warehouse","fas fa-weight","fas fa-wheelchair","fas fa-wifi","fas fa-window-close","fas fa-window-maximize","fas fa-window-minimize","fas fa-window-restore","fas fa-wine-glass","fas fa-won-sign","fas fa-wrench","fas fa-x-ray","fas fa-yen-sign","far fa-address-book","far fa-address-card","far fa-arrow-alt-circle-down","far fa-arrow-alt-circle-left","far fa-arrow-alt-circle-right","far fa-arrow-alt-circle-up","far fa-bell","far fa-bell-slash","far fa-bookmark","far fa-building","far fa-calendar","far fa-calendar-alt","far fa-calendar-check","far fa-calendar-minus","far fa-calendar-plus","far fa-calendar-times","far fa-caret-square-down","far fa-caret-square-left","far fa-caret-square-right","far fa-caret-square-up","far fa-chart-bar","far fa-check-circle","far fa-check-square","far fa-circle","far fa-clipboard","far fa-clock","far fa-clone","far fa-closed-captioning","far fa-comment","far fa-comment-alt","far fa-comments","far fa-compass","far fa-copy","far fa-copyright","far fa-credit-card","far fa-dot-circle","far fa-edit","far fa-envelope","far fa-envelope-open","far fa-eye-slash","far fa-file","far fa-file-alt","far fa-file-archive","far fa-file-audio","far fa-file-code","far fa-file-excel","far fa-file-image","far fa-file-pdf","far fa-file-powerpoint","far fa-file-video","far fa-file-word","far fa-flag","far fa-folder","far fa-folder-open","far fa-frown","far fa-futbol","far fa-gem","far fa-hand-lizard","far fa-hand-paper","far fa-hand-peace","far fa-hand-point-down","far fa-hand-point-left","far fa-hand-point-right","far fa-hand-point-up","far fa-hand-pointer","far fa-hand-rock","far fa-hand-scissors","far fa-hand-spock","far fa-handshake","far fa-hdd","far fa-heart","far fa-hospital","far fa-hourglass","far fa-id-badge","far fa-id-card","far fa-image","far fa-images","far fa-keyboard","far fa-lemon","far fa-life-ring","far fa-lightbulb","far fa-list-alt","far fa-map","far fa-meh","far fa-minus-square","far fa-money-bill-alt","far fa-moon","far fa-newspaper","far fa-object-group","far fa-object-ungroup","far fa-paper-plane","far fa-pause-circle","far fa-play-circle","far fa-plus-square","far fa-question-circle","far fa-registered","far fa-save","far fa-share-square","far fa-smile","far fa-snowflake","far fa-square","far fa-star","far fa-star-half","far fa-sticky-note","far fa-stop-circle","far fa-sun","far fa-thumbs-down","far fa-thumbs-up","far fa-times-circle","far fa-trash-alt","far fa-user","far fa-user-circle","far fa-window-close","far fa-window-maximize","far fa-window-minimize","far fa-window-restore","fab fa-500px","fab fa-accessible-icon","fab fa-accusoft","fab fa-adn","fab fa-adversal","fab fa-affiliatetheme","fab fa-algolia","fab fa-amazon","fab fa-amazon-pay","fab fa-amilia","fab fa-android","fab fa-angellist","fab fa-angrycreative","fab fa-angular","fab fa-app-store","fab fa-app-store-ios","fab fa-apper","fab fa-apple","fab fa-apple-pay","fab fa-asymmetrik","fab fa-audible","fab fa-autoprefixer","fab fa-avianex","fab fa-aviato","fab fa-aws","fab fa-bandcamp","fab fa-behance","fab fa-behance-square","fab fa-bimobject","fab fa-bitbucket","fab fa-bitcoin","fab fa-bity","fab fa-black-tie","fab fa-blackberry","fab fa-blogger","fab fa-blogger-b","fab fa-bluetooth","fab fa-bluetooth-b","fab fa-btc","fab fa-buromobelexperte","fab fa-buysellads","fab fa-cc-amazon-pay","fab fa-cc-amex","fab fa-cc-apple-pay","fab fa-cc-diners-club","fab fa-cc-discover","fab fa-cc-jcb","fab fa-cc-mastercard","fab fa-cc-paypal","fab fa-cc-stripe","fab fa-cc-visa","fab fa-centercode","fab fa-chrome","fab fa-cloudscale","fab fa-cloudsmith","fab fa-cloudversify","fab fa-codepen","fab fa-codiepie","fab fa-connectdevelop","fab fa-contao","fab fa-cpanel","fab fa-creative-commons","fab fa-css3","fab fa-css3-alt","fab fa-cuttlefish","fab fa-d-and-d","fab fa-dashcube","fab fa-delicious","fab fa-deploydog","fab fa-deskpro","fab fa-deviantart","fab fa-digg","fab fa-digital-ocean","fab fa-discord","fab fa-discourse","fab fa-dochub","fab fa-docker","fab fa-draft2digital","fab fa-dribbble","fab fa-dribbble-square","fab fa-dropbox","fab fa-drupal","fab fa-dyalog","fab fa-earlybirds","fab fa-edge","fab fa-elementor","fab fa-ember","fab fa-empire","fab fa-envira","fab fa-erlang","fab fa-ethereum","fab fa-etsy","fab fa-expeditedssl","fab fa-facebook","fab fa-facebook-f","fab fa-facebook-messenger","fab fa-facebook-square","fab fa-firefox","fab fa-first-order","fab fa-firstdraft","fab fa-flickr","fab fa-flipboard","fab fa-fly","fab fa-font-awesome","fab fa-font-awesome-alt","fab fa-font-awesome-flag","fab fa-fonticons","fab fa-fonticons-fi","fab fa-fort-awesome","fab fa-fort-awesome-alt","fab fa-forumbee","fab fa-foursquare","fab fa-free-code-camp","fab fa-freebsd","fab fa-get-pocket","fab fa-gg","fab fa-gg-circle","fab fa-git","fab fa-git-square","fab fa-github","fab fa-github-alt","fab fa-github-square","fab fa-gitkraken","fab fa-gitlab","fab fa-gitter","fab fa-glide","fab fa-glide-g","fab fa-gofore","fab fa-goodreads","fab fa-goodreads-g","fab fa-google","fab fa-google-drive","fab fa-google-play","fab fa-google-plus","fab fa-google-plus-g","fab fa-google-plus-square","fab fa-google-wallet","fab fa-gratipay","fab fa-grav","fab fa-gripfire","fab fa-grunt","fab fa-gulp","fab fa-hacker-news","fab fa-hacker-news-square","fab fa-hips","fab fa-hire-a-helper","fab fa-hooli","fab fa-hotjar","fab fa-houzz","fab fa-html5","fab fa-hubspot","fab fa-imdb","fab fa-instagram","fab fa-internet-explorer","fab fa-ioxhost","fab fa-itunes","fab fa-itunes-note","fab fa-jenkins","fab fa-joget","fab fa-joomla","fab fa-js","fab fa-js-square","fab fa-jsfiddle","fab fa-keycdn","fab fa-kickstarter","fab fa-kickstarter-k","fab fa-korvue","fab fa-laravel","fab fa-lastfm","fab fa-lastfm-square","fab fa-leanpub","fab fa-less","fab fa-line","fab fa-linkedin","fab fa-linkedin-in","fab fa-linode","fab fa-linux","fab fa-lyft","fab fa-magento","fab fa-maxcdn","fab fa-medapps","fab fa-medium","fab fa-medium-m","fab fa-medrt","fab fa-meetup","fab fa-microsoft","fab fa-mix","fab fa-mixcloud","fab fa-mizuni","fab fa-modx","fab fa-monero","fab fa-napster","fab fa-nintendo-switch","fab fa-node","fab fa-node-js","fab fa-npm","fab fa-ns8","fab fa-nutritionix","fab fa-odnoklassniki","fab fa-odnoklassniki-square","fab fa-opencart","fab fa-openid","fab fa-opera","fab fa-optin-monster","fab fa-osi","fab fa-page4","fab fa-pagelines","fab fa-palfed","fab fa-patreon","fab fa-paypal","fab fa-periscope","fab fa-phabricator","fab fa-phoenix-framework","fab fa-php","fab fa-pied-piper","fab fa-pied-piper-alt","fab fa-pied-piper-pp","fab fa-pinterest","fab fa-pinterest-p","fab fa-pinterest-square","fab fa-playstation","fab fa-product-hunt","fab fa-pushed","fab fa-python","fab fa-qq","fab fa-quinscape","fab fa-quora","fab fa-ravelry","fab fa-react","fab fa-readme","fab fa-rebel","fab fa-red-river","fab fa-reddit","fab fa-reddit-alien","fab fa-reddit-square","fab fa-rendact","fab fa-renren","fab fa-replyd","fab fa-resolving","fab fa-rocketchat","fab fa-rockrms","fab fa-safari","fab fa-sass","fab fa-schlix","fab fa-scribd","fab fa-searchengin","fab fa-sellcast","fab fa-sellsy","fab fa-servicestack","fab fa-shirtsinbulk","fab fa-simplybuilt","fab fa-sistrix","fab fa-skyatlas","fab fa-skype","fab fa-slack","fab fa-slack-hash","fab fa-slideshare","fab fa-snapchat","fab fa-snapchat-ghost","fab fa-snapchat-square","fab fa-soundcloud","fab fa-speakap","fab fa-spotify","fab fa-stack-exchange","fab fa-stack-overflow","fab fa-staylinked","fab fa-steam","fab fa-steam-square","fab fa-steam-symbol","fab fa-sticker-mule","fab fa-strava","fab fa-stripe","fab fa-stripe-s","fab fa-studiovinari","fab fa-stumbleupon","fab fa-stumbleupon-circle","fab fa-superpowers","fab fa-supple","fab fa-telegram","fab fa-telegram-plane","fab fa-tencent-weibo","fab fa-themeisle","fab fa-trello","fab fa-tripadvisor","fab fa-tumblr","fab fa-tumblr-square","fab fa-twitch","fab fa-twitter","fab fa-twitter-square","fab fa-typo3","fab fa-uber","fab fa-uikit","fab fa-uniregistry","fab fa-untappd","fab fa-usb","fab fa-ussunnah","fab fa-vaadin","fab fa-viacoin","fab fa-viadeo","fab fa-viadeo-square","fab fa-viber","fab fa-vimeo","fab fa-vimeo-square","fab fa-vimeo-v","fab fa-vine","fab fa-vk","fab fa-vnv","fab fa-vuejs","fab fa-weibo","fab fa-weixin","fab fa-whatsapp","fab fa-whatsapp-square","fab fa-whmcs","fab fa-wikipedia-w","fab fa-windows","fab fa-wordpress","fab fa-wordpress-simple","fab fa-wpbeginner","fab fa-wpexplorer","fab fa-wpforms","fab fa-xbox","fab fa-xing","fab fa-xing-square","fab fa-y-combinator","fab fa-yahoo","fab fa-yandex","fab fa-yandex-international","fab fa-yelp","fab fa-yoast","fab fa-youtube","fab fa-youtube-square" +} \ No newline at end of file diff --git a/public/lib/imgareaselect/css/border-anim-h.gif b/public/lib/imgareaselect/css/border-anim-h.gif new file mode 100755 index 0000000..ec9f5da Binary files /dev/null and b/public/lib/imgareaselect/css/border-anim-h.gif differ diff --git a/public/lib/imgareaselect/css/border-anim-v.gif b/public/lib/imgareaselect/css/border-anim-v.gif new file mode 100755 index 0000000..331cc90 Binary files /dev/null and b/public/lib/imgareaselect/css/border-anim-v.gif differ diff --git a/public/lib/imgareaselect/css/border-h.gif b/public/lib/imgareaselect/css/border-h.gif new file mode 100755 index 0000000..a2aa5b0 Binary files /dev/null and b/public/lib/imgareaselect/css/border-h.gif differ diff --git a/public/lib/imgareaselect/css/border-v.gif b/public/lib/imgareaselect/css/border-v.gif new file mode 100755 index 0000000..4bfd555 Binary files /dev/null and b/public/lib/imgareaselect/css/border-v.gif differ diff --git a/public/lib/imgareaselect/css/imgareaselect-animated.css b/public/lib/imgareaselect/css/imgareaselect-animated.css new file mode 100755 index 0000000..6ec6e10 --- /dev/null +++ b/public/lib/imgareaselect/css/imgareaselect-animated.css @@ -0,0 +1,41 @@ +/* + * imgAreaSelect animated border style + */ + +.imgareaselect-border1 { + background: url(border-anim-v.gif) repeat-y left top; +} + +.imgareaselect-border2 { + background: url(border-anim-h.gif) repeat-x left top; +} + +.imgareaselect-border3 { + background: url(border-anim-v.gif) repeat-y right top; +} + +.imgareaselect-border4 { + background: url(border-anim-h.gif) repeat-x left bottom; +} + +.imgareaselect-border1, .imgareaselect-border2, +.imgareaselect-border3, .imgareaselect-border4 { + filter: alpha(opacity=50); + opacity: 0.5; +} + +.imgareaselect-handle { + background-color: #fff; + border: solid 1px #000; + filter: alpha(opacity=50); + opacity: 0.5; +} + +.imgareaselect-outer { + background-color: #000; + filter: alpha(opacity=50); + opacity: 0.5; +} + +.imgareaselect-selection { +} \ No newline at end of file diff --git a/public/lib/imgareaselect/css/imgareaselect-default.css b/public/lib/imgareaselect/css/imgareaselect-default.css new file mode 100755 index 0000000..f4fe341 --- /dev/null +++ b/public/lib/imgareaselect/css/imgareaselect-default.css @@ -0,0 +1,41 @@ +/* + * imgAreaSelect default style + */ + +.imgareaselect-border1 { + background: url(border-v.gif) repeat-y left top; +} + +.imgareaselect-border2 { + background: url(border-h.gif) repeat-x left top; +} + +.imgareaselect-border3 { + background: url(border-v.gif) repeat-y right top; +} + +.imgareaselect-border4 { + background: url(border-h.gif) repeat-x left bottom; +} + +.imgareaselect-border1, .imgareaselect-border2, +.imgareaselect-border3, .imgareaselect-border4 { + filter: alpha(opacity=50); + opacity: 0.5; +} + +.imgareaselect-handle { + background-color: #fff; + border: solid 1px #000; + filter: alpha(opacity=50); + opacity: 0.5; +} + +.imgareaselect-outer { + background-color: #000; + filter: alpha(opacity=50); + opacity: 0.5; +} + +.imgareaselect-selection { +} \ No newline at end of file diff --git a/public/lib/imgareaselect/css/imgareaselect-deprecated.css b/public/lib/imgareaselect/css/imgareaselect-deprecated.css new file mode 100755 index 0000000..eaf0ddc --- /dev/null +++ b/public/lib/imgareaselect/css/imgareaselect-deprecated.css @@ -0,0 +1,36 @@ +/* + * imgAreaSelect style to be used with deprecated options + */ + +.imgareaselect-border1, .imgareaselect-border2, +.imgareaselect-border3, .imgareaselect-border4 { + filter: alpha(opacity=50); + opacity: 0.5; +} + +.imgareaselect-border1 { + border: solid 1px #000; +} + +.imgareaselect-border2 { + border: dashed 1px #fff; +} + +.imgareaselect-handle { + background-color: #fff; + border: solid 1px #000; + filter: alpha(opacity=50); + opacity: 0.5; +} + +.imgareaselect-outer { + background-color: #000; + filter: alpha(opacity=40); + opacity: 0.4; +} + +.imgareaselect-selection { + background-color: #fff; + filter: alpha(opacity=0); + opacity: 0; +} diff --git a/public/lib/imgareaselect/js/jquery.imgareaselect.dev.js b/public/lib/imgareaselect/js/jquery.imgareaselect.dev.js new file mode 100644 index 0000000..fe499a5 --- /dev/null +++ b/public/lib/imgareaselect/js/jquery.imgareaselect.dev.js @@ -0,0 +1,1205 @@ +/* + * imgAreaSelect jQuery plugin + * version 0.9.11-rc.1 + * + * Copyright (c) 2008-2013 Michal Wojciechowski (odyniec.net) + * + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * http://odyniec.net/projects/imgareaselect/ + * + */ + +(function($) { + +/* + * Math functions will be used extensively, so it's convenient to make a few + * shortcuts + */ +var abs = Math.abs, + max = Math.max, + min = Math.min, + round = Math.round; + +/** + * Create a new HTML div element + * + * @return A jQuery object representing the new element + */ +function div() { + return $('
'); +} + +/** + * imgAreaSelect initialization + * + * @param img + * A HTML image element to attach the plugin to + * @param options + * An options object + */ +$.imgAreaSelect = function (img, options) { + var + /* jQuery object representing the image */ + $img = $(img), + + /* Has the image finished loading? */ + imgLoaded, + + /* Plugin elements */ + + /* Container box */ + $box = div(), + /* Selection area */ + $area = div(), + /* Border (four divs) */ + $border = div().add(div()).add(div()).add(div()), + /* Outer area (four divs) */ + $outer = div().add(div()).add(div()).add(div()), + /* Handles (empty by default, initialized in setOptions()) */ + $handles = $([]), + + /* + * Additional element to work around a cursor problem in Opera + * (explained later) + */ + $areaOpera, + + /* Image position (relative to viewport) */ + left, top, + + /* Image offset (as returned by .offset()) */ + imgOfs = { left: 0, top: 0 }, + + /* Image dimensions (as returned by .width() and .height()) */ + imgWidth, imgHeight, + + /* + * jQuery object representing the parent element that the plugin + * elements are appended to + */ + $parent, + + /* Parent element offset (as returned by .offset()) */ + parOfs = { left: 0, top: 0 }, + + /* Base z-index for plugin elements */ + zIndex = 0, + + /* Plugin elements position */ + position = 'absolute', + + /* X/Y coordinates of the starting point for move/resize operations */ + startX, startY, + + /* Horizontal and vertical scaling factors */ + scaleX, scaleY, + + /* Current resize mode ("nw", "se", etc.) */ + resize, + + /* Selection area constraints */ + minWidth, minHeight, maxWidth, maxHeight, + + /* Aspect ratio to maintain (floating point number) */ + aspectRatio, + + /* Are the plugin elements currently displayed? */ + shown, + + /* Current selection (relative to parent element) */ + x1, y1, x2, y2, + + /* Current selection (relative to scaled image) */ + selection = { x1: 0, y1: 0, x2: 0, y2: 0, width: 0, height: 0 }, + + /* Document element */ + docElem = document.documentElement, + + /* User agent */ + ua = navigator.userAgent, + + /* Various helper variables used throughout the code */ + $p, d, i, o, w, h, adjusted; + + /* + * Translate selection coordinates (relative to scaled image) to viewport + * coordinates (relative to parent element) + */ + + /** + * Translate selection X to viewport X + * + * @param x + * Selection X + * @return Viewport X + */ + function viewX(x) { + return x + imgOfs.left - parOfs.left; + } + + /** + * Translate selection Y to viewport Y + * + * @param y + * Selection Y + * @return Viewport Y + */ + function viewY(y) { + return y + imgOfs.top - parOfs.top; + } + + /* + * Translate viewport coordinates to selection coordinates + */ + + /** + * Translate viewport X to selection X + * + * @param x + * Viewport X + * @return Selection X + */ + function selX(x) { + return x - imgOfs.left + parOfs.left; + } + + /** + * Translate viewport Y to selection Y + * + * @param y + * Viewport Y + * @return Selection Y + */ + function selY(y) { + return y - imgOfs.top + parOfs.top; + } + + /* + * Translate event coordinates (relative to document) to viewport + * coordinates + */ + + /** + * Get event X and translate it to viewport X + * + * @param event + * The event object + * @return Viewport X + */ + function evX(event) { + return event.pageX - parOfs.left; + } + + /** + * Get event Y and translate it to viewport Y + * + * @param event + * The event object + * @return Viewport Y + */ + function evY(event) { + return event.pageY - parOfs.top; + } + + /** + * Get the current selection + * + * @param noScale + * If set to true, scaling is not applied to the + * returned selection + * @return Selection object + */ + function getSelection(noScale) { + var sx = noScale || scaleX, sy = noScale || scaleY; + + return { x1: round(selection.x1 * sx), + y1: round(selection.y1 * sy), + x2: round(selection.x2 * sx), + y2: round(selection.y2 * sy), + width: round(selection.x2 * sx) - round(selection.x1 * sx), + height: round(selection.y2 * sy) - round(selection.y1 * sy) }; + } + + /** + * Set the current selection + * + * @param x1 + * X coordinate of the upper left corner of the selection area + * @param y1 + * Y coordinate of the upper left corner of the selection area + * @param x2 + * X coordinate of the lower right corner of the selection area + * @param y2 + * Y coordinate of the lower right corner of the selection area + * @param noScale + * If set to true, scaling is not applied to the + * new selection + */ + function setSelection(x1, y1, x2, y2, noScale) { + var sx = noScale || scaleX, sy = noScale || scaleY; + + selection = { + x1: round(x1 / sx || 0), + y1: round(y1 / sy || 0), + x2: round(x2 / sx || 0), + y2: round(y2 / sy || 0) + }; + + selection.width = selection.x2 - selection.x1; + selection.height = selection.y2 - selection.y1; + } + + /** + * Recalculate image and parent offsets + */ + function adjust() { + /* + * Do not adjust if image has not yet loaded or if width is not a + * positive number. The latter might happen when imgAreaSelect is put + * on a parent element which is then hidden. + */ + if (!imgLoaded || !$img.width()) + return; + + /* + * Get image offset. The .offset() method returns float values, so they + * need to be rounded. + */ + imgOfs = { left: round($img.offset().left), top: round($img.offset().top) }; + + /* Get image dimensions */ + imgWidth = $img.innerWidth(); + imgHeight = $img.innerHeight(); + + imgOfs.top += ($img.outerHeight() - imgHeight) >> 1; + imgOfs.left += ($img.outerWidth() - imgWidth) >> 1; + + /* Set minimum and maximum selection area dimensions */ + minWidth = round(options.minWidth / scaleX) || 0; + minHeight = round(options.minHeight / scaleY) || 0; + maxWidth = round(min(options.maxWidth / scaleX || 1<<24, imgWidth)); + maxHeight = round(min(options.maxHeight / scaleY || 1<<24, imgHeight)); + + /* + * Workaround for jQuery 1.3.2 incorrect offset calculation, originally + * observed in Safari 3. Firefox 2 is also affected. + */ + if ($().jquery == '1.3.2' && position == 'fixed' && + !docElem['getBoundingClientRect']) + { + imgOfs.top += max(document.body.scrollTop, docElem.scrollTop); + imgOfs.left += max(document.body.scrollLeft, docElem.scrollLeft); + } + + /* Determine parent element offset */ + parOfs = /absolute|relative/.test($parent.css('position')) ? + { left: round($parent.offset().left) - $parent.scrollLeft(), + top: round($parent.offset().top) - $parent.scrollTop() } : + position == 'fixed' ? + { left: $(document).scrollLeft(), top: $(document).scrollTop() } : + { left: 0, top: 0 }; + + left = viewX(0); + top = viewY(0); + + /* + * Check if selection area is within image boundaries, adjust if + * necessary + */ + if (selection.x2 > imgWidth || selection.y2 > imgHeight) + doResize(); + } + + /** + * Update plugin elements + * + * @param resetKeyPress + * If set to false, this instance's keypress + * event handler is not activated + */ + function update(resetKeyPress) { + /* If plugin elements are hidden, do nothing */ + if (!shown) return; + + /* + * Set the position and size of the container box and the selection area + * inside it + */ + $box.css({ left: viewX(selection.x1), top: viewY(selection.y1) }) + .add($area).width(w = selection.width).height(h = selection.height); + + /* + * Reset the position of selection area, borders, and handles (IE6/IE7 + * position them incorrectly if we don't do this) + */ + $area.add($border).add($handles).css({ left: 0, top: 0 }); + + /* Set border dimensions */ + $border + .width(max(w - $border.outerWidth() + $border.innerWidth(), 0)) + .height(max(h - $border.outerHeight() + $border.innerHeight(), 0)); + + /* Arrange the outer area elements */ + $($outer[0]).css({ left: left, top: top, + width: selection.x1, height: imgHeight }); + $($outer[1]).css({ left: left + selection.x1, top: top, + width: w, height: selection.y1 }); + $($outer[2]).css({ left: left + selection.x2, top: top, + width: imgWidth - selection.x2, height: imgHeight }); + $($outer[3]).css({ left: left + selection.x1, top: top + selection.y2, + width: w, height: imgHeight - selection.y2 }); + + w -= $handles.outerWidth(); + h -= $handles.outerHeight(); + + /* Arrange handles */ + switch ($handles.length) { + case 8: + $($handles[4]).css({ left: w >> 1 }); + $($handles[5]).css({ left: w, top: h >> 1 }); + $($handles[6]).css({ left: w >> 1, top: h }); + $($handles[7]).css({ top: h >> 1 }); + case 4: + $handles.slice(1,3).css({ left: w }); + $handles.slice(2,4).css({ top: h }); + } + + if (resetKeyPress !== false) { + /* + * Need to reset the document keypress event handler -- unbind the + * current handler + */ + if ($.imgAreaSelect.onKeyPress != docKeyPress) + $(document).unbind($.imgAreaSelect.keyPress, + $.imgAreaSelect.onKeyPress); + + if (options.keys) + /* + * Set the document keypress event handler to this instance's + * docKeyPress() function + */ + $(document)[$.imgAreaSelect.keyPress]( + $.imgAreaSelect.onKeyPress = docKeyPress); + } + + /* + * Internet Explorer displays 1px-wide dashed borders incorrectly by + * filling the spaces between dashes with white. Toggling the margin + * property between 0 and "auto" fixes this in IE6 and IE7 (IE8 is still + * broken). This workaround is not perfect, as it requires setTimeout() + * and thus causes the border to flicker a bit, but I haven't found a + * better solution. + * + * Note: This only happens with CSS borders, set with the borderWidth, + * borderOpacity, borderColor1, and borderColor2 options (which are now + * deprecated). Borders created with GIF background images are fine. + */ + if (msie && $border.outerWidth() - $border.innerWidth() == 2) { + $border.css('margin', 0); + setTimeout(function () { $border.css('margin', 'auto'); }, 0); + } + } + + /** + * Do the complete update sequence: recalculate offsets, update the + * elements, and set the correct values of x1, y1, x2, and y2. + * + * @param resetKeyPress + * If set to false, this instance's keypress + * event handler is not activated + */ + function doUpdate(resetKeyPress) { + adjust(); + update(resetKeyPress); + x1 = viewX(selection.x1); y1 = viewY(selection.y1); + x2 = viewX(selection.x2); y2 = viewY(selection.y2); + } + + /** + * Hide or fade out an element (or multiple elements) + * + * @param $elem + * A jQuery object containing the element(s) to hide/fade out + * @param fn + * Callback function to be called when fadeOut() completes + */ + function hide($elem, fn) { + options.fadeSpeed ? $elem.fadeOut(options.fadeSpeed, fn) : $elem.hide(); + } + + /** + * Selection area mousemove event handler + * + * @param event + * The event object + */ + function areaMouseMove(event) { + var x = selX(evX(event)) - selection.x1, + y = selY(evY(event)) - selection.y1; + + if (!adjusted) { + adjust(); + adjusted = true; + + $box.one('mouseout', function () { adjusted = false; }); + } + + /* Clear the resize mode */ + resize = ''; + + if (options.resizable) { + /* + * Check if the mouse pointer is over the resize margin area and set + * the resize mode accordingly + */ + if (y <= options.resizeMargin) + resize = 'n'; + else if (y >= selection.height - options.resizeMargin) + resize = 's'; + if (x <= options.resizeMargin) + resize += 'w'; + else if (x >= selection.width - options.resizeMargin) + resize += 'e'; + } + + $box.css('cursor', resize ? resize + '-resize' : + options.movable ? 'move' : ''); + if ($areaOpera) + $areaOpera.toggle(); + } + + /** + * Document mouseup event handler + * + * @param event + * The event object + */ + function docMouseUp(event) { + /* Set back the default cursor */ + $('body').css('cursor', ''); + /* + * If autoHide is enabled, or if the selection has zero width/height, + * hide the selection and the outer area + */ + if (options.autoHide || selection.width * selection.height == 0) + hide($box.add($outer), function () { $(this).hide(); }); + + $(document).unbind('mousemove', selectingMouseMove); + $box.mousemove(areaMouseMove); + + options.onSelectEnd(img, getSelection()); + } + + /** + * Selection area mousedown event handler + * + * @param event + * The event object + * @return false + */ + function areaMouseDown(event) { + if (event.which != 1) return false; + + adjust(); + + if (resize) { + /* Resize mode is in effect */ + $('body').css('cursor', resize + '-resize'); + + x1 = viewX(selection[/w/.test(resize) ? 'x2' : 'x1']); + y1 = viewY(selection[/n/.test(resize) ? 'y2' : 'y1']); + + $(document).mousemove(selectingMouseMove) + .one('mouseup', docMouseUp); + $box.unbind('mousemove', areaMouseMove); + } + else if (options.movable) { + startX = left + selection.x1 - evX(event); + startY = top + selection.y1 - evY(event); + + $box.unbind('mousemove', areaMouseMove); + + $(document).mousemove(movingMouseMove) + .one('mouseup', function () { + options.onSelectEnd(img, getSelection()); + + $(document).unbind('mousemove', movingMouseMove); + $box.mousemove(areaMouseMove); + }); + } + else + $img.mousedown(event); + + return false; + } + + /** + * Adjust the x2/y2 coordinates to maintain aspect ratio (if defined) + * + * @param xFirst + * If set to true, calculate x2 first. Otherwise, + * calculate y2 first. + */ + function fixAspectRatio(xFirst) { + if (aspectRatio) + if (xFirst) { + x2 = max(left, min(left + imgWidth, + x1 + abs(y2 - y1) * aspectRatio * (x2 > x1 || -1))); + y2 = round(max(top, min(top + imgHeight, + y1 + abs(x2 - x1) / aspectRatio * (y2 > y1 || -1)))); + x2 = round(x2); + } + else { + y2 = max(top, min(top + imgHeight, + y1 + abs(x2 - x1) / aspectRatio * (y2 > y1 || -1))); + x2 = round(max(left, min(left + imgWidth, + x1 + abs(y2 - y1) * aspectRatio * (x2 > x1 || -1)))); + y2 = round(y2); + } + } + + /** + * Resize the selection area respecting the minimum/maximum dimensions and + * aspect ratio + */ + function doResize() { + /* + * Make sure the top left corner of the selection area stays within + * image boundaries (it might not if the image source was dynamically + * changed). + */ + x1 = min(x1, left + imgWidth); + y1 = min(y1, top + imgHeight); + + if (abs(x2 - x1) < minWidth) { + /* Selection width is smaller than minWidth */ + x2 = x1 - minWidth * (x2 < x1 || -1); + + if (x2 < left) + x1 = left + minWidth; + else if (x2 > left + imgWidth) + x1 = left + imgWidth - minWidth; + } + + if (abs(y2 - y1) < minHeight) { + /* Selection height is smaller than minHeight */ + y2 = y1 - minHeight * (y2 < y1 || -1); + + if (y2 < top) + y1 = top + minHeight; + else if (y2 > top + imgHeight) + y1 = top + imgHeight - minHeight; + } + + x2 = max(left, min(x2, left + imgWidth)); + y2 = max(top, min(y2, top + imgHeight)); + + fixAspectRatio(abs(x2 - x1) < abs(y2 - y1) * aspectRatio); + + if (abs(x2 - x1) > maxWidth) { + /* Selection width is greater than maxWidth */ + x2 = x1 - maxWidth * (x2 < x1 || -1); + fixAspectRatio(); + } + + if (abs(y2 - y1) > maxHeight) { + /* Selection height is greater than maxHeight */ + y2 = y1 - maxHeight * (y2 < y1 || -1); + fixAspectRatio(true); + } + + selection = { x1: selX(min(x1, x2)), x2: selX(max(x1, x2)), + y1: selY(min(y1, y2)), y2: selY(max(y1, y2)), + width: abs(x2 - x1), height: abs(y2 - y1) }; + + update(); + + options.onSelectChange(img, getSelection()); + } + + /** + * Mousemove event handler triggered when the user is selecting an area + * + * @param event + * The event object + * @return false + */ + function selectingMouseMove(event) { + x2 = /w|e|^$/.test(resize) || aspectRatio ? evX(event) : viewX(selection.x2); + y2 = /n|s|^$/.test(resize) || aspectRatio ? evY(event) : viewY(selection.y2); + + doResize(); + + return false; + } + + /** + * Move the selection area + * + * @param newX1 + * New viewport X1 + * @param newY1 + * New viewport Y1 + */ + function doMove(newX1, newY1) { + x2 = (x1 = newX1) + selection.width; + y2 = (y1 = newY1) + selection.height; + + $.extend(selection, { x1: selX(x1), y1: selY(y1), x2: selX(x2), + y2: selY(y2) }); + + update(); + + options.onSelectChange(img, getSelection()); + } + + /** + * Mousemove event handler triggered when the selection area is being moved + * + * @param event + * The event object + * @return false + */ + function movingMouseMove(event) { + x1 = max(left, min(startX + evX(event), left + imgWidth - selection.width)); + y1 = max(top, min(startY + evY(event), top + imgHeight - selection.height)); + + doMove(x1, y1); + + event.preventDefault(); + return false; + } + + /** + * Start selection + */ + function startSelection() { + $(document).unbind('mousemove', startSelection); + adjust(); + + x2 = x1; + y2 = y1; + doResize(); + + resize = ''; + + if (!$outer.is(':visible')) + /* Show the plugin elements */ + $box.add($outer).hide().fadeIn(options.fadeSpeed||0); + + shown = true; + + $(document).unbind('mouseup', cancelSelection) + .mousemove(selectingMouseMove).one('mouseup', docMouseUp); + $box.unbind('mousemove', areaMouseMove); + + options.onSelectStart(img, getSelection()); + } + + /** + * Cancel selection + */ + function cancelSelection() { + $(document).unbind('mousemove', startSelection) + .unbind('mouseup', cancelSelection); + hide($box.add($outer)); + + setSelection(selX(x1), selY(y1), selX(x1), selY(y1)); + + /* If this is an API call, callback functions should not be triggered */ + if (!(this instanceof $.imgAreaSelect)) { + options.onSelectChange(img, getSelection()); + options.onSelectEnd(img, getSelection()); + } + } + + /** + * Image mousedown event handler + * + * @param event + * The event object + * @return false + */ + function imgMouseDown(event) { + /* Ignore the event if animation is in progress */ + if (event.which != 1 || $outer.is(':animated')) return false; + + adjust(); + startX = x1 = evX(event); + startY = y1 = evY(event); + + /* Selection will start when the mouse is moved */ + $(document).mousemove(startSelection).mouseup(cancelSelection); + + return false; + } + + /** + * Window resize event handler + */ + function windowResize() { + doUpdate(false); + } + + /** + * Image load event handler. This is the final part of the initialization + * process. + */ + function imgLoad() { + imgLoaded = true; + + /* Set options */ + setOptions(options = $.extend({ + classPrefix: 'imgareaselect', + movable: true, + parent: 'body', + resizable: true, + resizeMargin: 10, + onInit: function () {}, + onSelectStart: function () {}, + onSelectChange: function () {}, + onSelectEnd: function () {} + }, options)); + + $box.add($outer).css({ visibility: '' }); + + if (options.show) { + shown = true; + adjust(); + update(); + $box.add($outer).hide().fadeIn(options.fadeSpeed||0); + } + + /* + * Call the onInit callback. The setTimeout() call is used to ensure + * that the plugin has been fully initialized and the object instance is + * available (so that it can be obtained in the callback). + */ + setTimeout(function () { options.onInit(img, getSelection()); }, 0); + } + + /** + * Document keypress event handler + * + * @param event + * The event object + * @return false + */ + var docKeyPress = function(event) { + var k = options.keys, d, t, key = event.keyCode; + + d = !isNaN(k.alt) && (event.altKey || event.originalEvent.altKey) ? k.alt : + !isNaN(k.ctrl) && event.ctrlKey ? k.ctrl : + !isNaN(k.shift) && event.shiftKey ? k.shift : + !isNaN(k.arrows) ? k.arrows : 10; + + if (k.arrows == 'resize' || (k.shift == 'resize' && event.shiftKey) || + (k.ctrl == 'resize' && event.ctrlKey) || + (k.alt == 'resize' && (event.altKey || event.originalEvent.altKey))) + { + /* Resize selection */ + + switch (key) { + case 37: + /* Left */ + d = -d; + case 39: + /* Right */ + t = max(x1, x2); + x1 = min(x1, x2); + x2 = max(t + d, x1); + fixAspectRatio(); + break; + case 38: + /* Up */ + d = -d; + case 40: + /* Down */ + t = max(y1, y2); + y1 = min(y1, y2); + y2 = max(t + d, y1); + fixAspectRatio(true); + break; + default: + return; + } + + doResize(); + } + else { + /* Move selection */ + + x1 = min(x1, x2); + y1 = min(y1, y2); + + switch (key) { + case 37: + /* Left */ + doMove(max(x1 - d, left), y1); + break; + case 38: + /* Up */ + doMove(x1, max(y1 - d, top)); + break; + case 39: + /* Right */ + doMove(x1 + min(d, imgWidth - selX(x2)), y1); + break; + case 40: + /* Down */ + doMove(x1, y1 + min(d, imgHeight - selY(y2))); + break; + default: + return; + } + } + + return false; + }; + + /** + * Apply style options to plugin element (or multiple elements) + * + * @param $elem + * A jQuery object representing the element(s) to style + * @param props + * An object that maps option names to corresponding CSS + * properties + */ + function styleOptions($elem, props) { + for (var option in props) + if (options[option] !== undefined) + $elem.css(props[option], options[option]); + } + + /** + * Set plugin options + * + * @param newOptions + * The new options object + */ + function setOptions(newOptions) { + if (newOptions.parent) + ($parent = $(newOptions.parent)).append($box).append($outer); + + /* Merge the new options with the existing ones */ + $.extend(options, newOptions); + + adjust(); + + if (newOptions.handles != null) { + /* Recreate selection area handles */ + $handles.remove(); + $handles = $([]); + + i = newOptions.handles ? newOptions.handles == 'corners' ? 4 : 8 : 0; + + while (i--) + $handles = $handles.add(div()); + + /* Add a class to handles and set the CSS properties */ + $handles.addClass(options.classPrefix + '-handle').css({ + position: 'absolute', + /* + * The font-size property needs to be set to zero, otherwise + * Internet Explorer makes the handles too large + */ + fontSize: 0, + zIndex: zIndex + 1 || 1 + }); + + /* + * If handle width/height has not been set with CSS rules, set the + * default 5px + */ + if (!parseInt($handles.css('width')) >= 0) + $handles.width(5).height(5); + + /* + * If the borderWidth option is in use, add a solid border to + * handles + */ + if (o = options.borderWidth) + $handles.css({ borderWidth: o, borderStyle: 'solid' }); + + /* Apply other style options */ + styleOptions($handles, { borderColor1: 'border-color', + borderColor2: 'background-color', + borderOpacity: 'opacity' }); + } + + /* Calculate scale factors */ + scaleX = options.imageWidth / imgWidth || 1; + scaleY = options.imageHeight / imgHeight || 1; + + /* Set selection */ + if (newOptions.x1 != null) { + setSelection(newOptions.x1, newOptions.y1, newOptions.x2, + newOptions.y2); + newOptions.show = !newOptions.hide; + } + + if (newOptions.keys) + /* Enable keyboard support */ + options.keys = $.extend({ shift: 1, ctrl: 'resize' }, + newOptions.keys); + + /* Add classes to plugin elements */ + $outer.addClass(options.classPrefix + '-outer'); + $area.addClass(options.classPrefix + '-selection'); + for (i = 0; i++ < 4;) + $($border[i-1]).addClass(options.classPrefix + '-border' + i); + + /* Apply style options */ + styleOptions($area, { selectionColor: 'background-color', + selectionOpacity: 'opacity' }); + styleOptions($border, { borderOpacity: 'opacity', + borderWidth: 'border-width' }); + styleOptions($outer, { outerColor: 'background-color', + outerOpacity: 'opacity' }); + if (o = options.borderColor1) + $($border[0]).css({ borderStyle: 'solid', borderColor: o }); + if (o = options.borderColor2) + $($border[1]).css({ borderStyle: 'dashed', borderColor: o }); + + /* Append all the selection area elements to the container box */ + $box.append($area.add($border).add($areaOpera)).append($handles); + + if (msie) { + if (o = ($outer.css('filter')||'').match(/opacity=(\d+)/)) + $outer.css('opacity', o[1]/100); + if (o = ($border.css('filter')||'').match(/opacity=(\d+)/)) + $border.css('opacity', o[1]/100); + } + + if (newOptions.hide) + hide($box.add($outer)); + else if (newOptions.show && imgLoaded) { + shown = true; + $box.add($outer).fadeIn(options.fadeSpeed||0); + doUpdate(); + } + + /* Calculate the aspect ratio factor */ + aspectRatio = (d = (options.aspectRatio || '').split(/:/))[0] / d[1]; + + $img.add($outer).unbind('mousedown', imgMouseDown); + + if (options.disable || options.enable === false) { + /* Disable the plugin */ + $box.unbind('mousemove', areaMouseMove).unbind('mousedown', areaMouseDown); + $(window).unbind('resize', windowResize); + } + else { + if (options.enable || options.disable === false) { + /* Enable the plugin */ + if (options.resizable || options.movable) + $box.mousemove(areaMouseMove).mousedown(areaMouseDown); + + $(window).resize(windowResize); + } + + if (!options.persistent) + $img.add($outer).mousedown(imgMouseDown); + } + + options.enable = options.disable = undefined; + } + + /** + * Remove plugin completely + */ + this.remove = function () { + /* + * Call setOptions with { disable: true } to unbind the event handlers + */ + setOptions({ disable: true }); + $box.add($outer).remove(); + }; + + /* + * Public API + */ + + /** + * Get current options + * + * @return An object containing the set of options currently in use + */ + this.getOptions = function () { return options; }; + + /** + * Set plugin options + * + * @param newOptions + * The new options object + */ + this.setOptions = setOptions; + + /** + * Get the current selection + * + * @param noScale + * If set to true, scaling is not applied to the + * returned selection + * @return Selection object + */ + this.getSelection = getSelection; + + /** + * Set the current selection + * + * @param x1 + * X coordinate of the upper left corner of the selection area + * @param y1 + * Y coordinate of the upper left corner of the selection area + * @param x2 + * X coordinate of the lower right corner of the selection area + * @param y2 + * Y coordinate of the lower right corner of the selection area + * @param noScale + * If set to true, scaling is not applied to the + * new selection + */ + this.setSelection = setSelection; + + /** + * Cancel selection + */ + this.cancelSelection = cancelSelection; + + /** + * Update plugin elements + * + * @param resetKeyPress + * If set to false, this instance's keypress + * event handler is not activated + */ + this.update = doUpdate; + + /* Do the dreaded browser detection */ + var msie = (/msie ([\w.]+)/i.exec(ua)||[])[1], + opera = /opera/i.test(ua), + safari = /webkit/i.test(ua) && !/chrome/i.test(ua); + + /* + * Traverse the image's parent elements (up to ) and find the + * highest z-index + */ + $p = $img; + + while ($p.length) { + zIndex = max(zIndex, + !isNaN($p.css('z-index')) ? $p.css('z-index') : zIndex); + /* Also check if any of the ancestor elements has fixed position */ + if ($p.css('position') == 'fixed') + position = 'fixed'; + + $p = $p.parent(':not(body)'); + } + + /* + * If z-index is given as an option, it overrides the one found by the + * above loop + */ + zIndex = options.zIndex || zIndex; + + if (msie) + $img.attr('unselectable', 'on'); + + /* + * In MSIE and WebKit, we need to use the keydown event instead of keypress + */ + $.imgAreaSelect.keyPress = msie || safari ? 'keydown' : 'keypress'; + + /* + * There is a bug affecting the CSS cursor property in Opera (observed in + * versions up to 10.00) that prevents the cursor from being updated unless + * the mouse leaves and enters the element again. To trigger the mouseover + * event, we're adding an additional div to $box and we're going to toggle + * it when mouse moves inside the selection area. + */ + if (opera) + $areaOpera = div().css({ width: '100%', height: '100%', + position: 'absolute', zIndex: zIndex + 2 || 2 }); + + /* + * We initially set visibility to "hidden" as a workaround for a weird + * behaviour observed in Google Chrome 1.0.154.53 (on Windows XP). Normally + * we would just set display to "none", but, for some reason, if we do so + * then Chrome refuses to later display the element with .show() or + * .fadeIn(). + */ + $box.add($outer).css({ visibility: 'hidden', position: position, + overflow: 'hidden', zIndex: zIndex || '0' }); + $box.css({ zIndex: zIndex + 2 || 2 }); + $area.add($border).css({ position: 'absolute', fontSize: 0 }); + + /* + * If the image has been fully loaded, or if it is not really an image (eg. + * a div), call imgLoad() immediately; otherwise, bind it to be called once + * on image load event. + */ + img.complete || img.readyState == 'complete' || !$img.is('img') ? + imgLoad() : $img.one('load', imgLoad); + + /* + * MSIE 9.0 doesn't always fire the image load event -- resetting the src + * attribute seems to trigger it. The check is for version 7 and above to + * accommodate for MSIE 9 running in compatibility mode. + */ + if (!imgLoaded && msie && msie >= 7) + img.src = img.src; +}; + +/** + * Invoke imgAreaSelect on a jQuery object containing the image(s) + * + * @param options + * Options object + * @return The jQuery object or a reference to imgAreaSelect instance (if the + * instance option was specified) + */ +$.fn.imgAreaSelect = function (options) { + options = options || {}; + + this.each(function () { + /* Is there already an imgAreaSelect instance bound to this element? */ + if ($(this).data('imgAreaSelect')) { + /* Yes there is -- is it supposed to be removed? */ + if (options.remove) { + /* Remove the plugin */ + $(this).data('imgAreaSelect').remove(); + $(this).removeData('imgAreaSelect'); + } + else + /* Reset options */ + $(this).data('imgAreaSelect').setOptions(options); + } + else if (!options.remove) { + /* No exising instance -- create a new one */ + + /* + * If neither the "enable" nor the "disable" option is present, add + * "enable" as the default + */ + if (options.enable === undefined && options.disable === undefined) + options.enable = true; + + $(this).data('imgAreaSelect', new $.imgAreaSelect(this, options)); + } + }); + + if (options.instance) + /* + * Return the imgAreaSelect instance bound to the first element in the + * set + */ + return $(this).data('imgAreaSelect'); + + return this; +}; + +})(jQuery); diff --git a/public/lib/select2/select2.init.js b/public/lib/select2/select2.init.js index f2217fb..f10276d 100644 --- a/public/lib/select2/select2.init.js +++ b/public/lib/select2/select2.init.js @@ -1,5 +1,4 @@ -(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/fr",[],function(){return{errorLoading:function(){return"Les résultats ne peuvent pas être chargés."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Supprimez "+t+" caractère"+(t>1)?"s":""},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Saisissez au moins "+t+" caractère"+(t>1)?"s":""},loadingMore:function(){return"Chargement de résultats supplémentaires…"},maximumSelected:function(e){return"Vous pouvez seulement sélectionner "+e.maximum+" élément"+(e.maximum>1)?"s":""},noResults:function(){return"Aucun résultat trouvé"},searching:function(){return"Recherche en cours…"}}}),{define:e.define,require:e.require}})(); -$(() => { +$(document).ready(function(){ $('.select2').select2( { language: "fr", diff --git a/public/uploads/avatar/6755c306c70e3.jpg b/public/uploads/avatar/6755c306c70e3.jpg new file mode 100644 index 0000000..a53a104 Binary files /dev/null and b/public/uploads/avatar/6755c306c70e3.jpg differ diff --git a/public/uploads/avatar/6755c33c48442.jpg b/public/uploads/avatar/6755c33c48442.jpg new file mode 100644 index 0000000..a53a104 Binary files /dev/null and b/public/uploads/avatar/6755c33c48442.jpg differ diff --git a/public/uploads/avatar/6755c3e4605d5.jpeg b/public/uploads/avatar/6755c3e4605d5.jpeg new file mode 100644 index 0000000..358dc36 Binary files /dev/null and b/public/uploads/avatar/6755c3e4605d5.jpeg differ diff --git a/public/uploads/avatar/6755c480910c9.jpg b/public/uploads/avatar/6755c480910c9.jpg new file mode 100644 index 0000000..0848e09 Binary files /dev/null and b/public/uploads/avatar/6755c480910c9.jpg differ diff --git a/public/uploads/avatar/6755c4acac2c8.jpg b/public/uploads/avatar/6755c4acac2c8.jpg new file mode 100644 index 0000000..a53a104 Binary files /dev/null and b/public/uploads/avatar/6755c4acac2c8.jpg differ diff --git a/public/uploads/avatar/6755c5ad0b1fb.jpeg b/public/uploads/avatar/6755c5ad0b1fb.jpeg new file mode 100644 index 0000000..358dc36 Binary files /dev/null and b/public/uploads/avatar/6755c5ad0b1fb.jpeg differ diff --git a/public/uploads/avatar/6755c5bc9f6af.jpg b/public/uploads/avatar/6755c5bc9f6af.jpg new file mode 100644 index 0000000..0848e09 Binary files /dev/null and b/public/uploads/avatar/6755c5bc9f6af.jpg differ diff --git a/public/uploads/avatar/6755c5d54e967.jpeg b/public/uploads/avatar/6755c5d54e967.jpeg new file mode 100644 index 0000000..358dc36 Binary files /dev/null and b/public/uploads/avatar/6755c5d54e967.jpeg differ diff --git a/public/uploads/avatar/6755c63be9d98.jpg b/public/uploads/avatar/6755c63be9d98.jpg new file mode 100644 index 0000000..0848e09 Binary files /dev/null and b/public/uploads/avatar/6755c63be9d98.jpg differ diff --git a/public/uploads/avatar/6755cd1809e70.jpg b/public/uploads/avatar/6755cd1809e70.jpg new file mode 100644 index 0000000..a803a58 Binary files /dev/null and b/public/uploads/avatar/6755cd1809e70.jpg differ diff --git a/public/uploads/avatar/6755cd47262e7.jpg b/public/uploads/avatar/6755cd47262e7.jpg new file mode 100644 index 0000000..0848e09 Binary files /dev/null and b/public/uploads/avatar/6755cd47262e7.jpg differ diff --git a/public/uploads/avatar/6755cd8c6ead0.webp b/public/uploads/avatar/6755cd8c6ead0.webp new file mode 100644 index 0000000..68f1603 Binary files /dev/null and b/public/uploads/avatar/6755cd8c6ead0.webp differ diff --git a/public/uploads/avatar/6755cded42349.jpg b/public/uploads/avatar/6755cded42349.jpg new file mode 100644 index 0000000..a53a104 Binary files /dev/null and b/public/uploads/avatar/6755cded42349.jpg differ diff --git a/public/uploads/avatar/6755ce2851b15.jpeg b/public/uploads/avatar/6755ce2851b15.jpeg new file mode 100644 index 0000000..358dc36 Binary files /dev/null and b/public/uploads/avatar/6755ce2851b15.jpeg differ diff --git a/public/uploads/avatar/6755ce9065632.jpg b/public/uploads/avatar/6755ce9065632.jpg new file mode 100644 index 0000000..d7e0522 Binary files /dev/null and b/public/uploads/avatar/6755ce9065632.jpg differ diff --git a/public/uploads/avatar/6755cea677d58.webp b/public/uploads/avatar/6755cea677d58.webp new file mode 100644 index 0000000..68f1603 Binary files /dev/null and b/public/uploads/avatar/6755cea677d58.webp differ diff --git a/public/uploads/avatar/6755ceb7b5b2b.jpg b/public/uploads/avatar/6755ceb7b5b2b.jpg new file mode 100644 index 0000000..d7e0522 Binary files /dev/null and b/public/uploads/avatar/6755ceb7b5b2b.jpg differ diff --git a/public/uploads/avatar/6755cf4965e56.jpg b/public/uploads/avatar/6755cf4965e56.jpg new file mode 100644 index 0000000..a53a104 Binary files /dev/null and b/public/uploads/avatar/6755cf4965e56.jpg differ diff --git a/public/uploads/avatar/6755cf71f0a2e.jpg b/public/uploads/avatar/6755cf71f0a2e.jpg new file mode 100644 index 0000000..d7e0522 Binary files /dev/null and b/public/uploads/avatar/6755cf71f0a2e.jpg differ diff --git a/public/uploads/avatar/6755d03b757e8.jpg b/public/uploads/avatar/6755d03b757e8.jpg new file mode 100644 index 0000000..d7e0522 Binary files /dev/null and b/public/uploads/avatar/6755d03b757e8.jpg differ diff --git a/public/uploads/avatar/6755d0f260125.jpg b/public/uploads/avatar/6755d0f260125.jpg new file mode 100644 index 0000000..d7e0522 Binary files /dev/null and b/public/uploads/avatar/6755d0f260125.jpg differ diff --git a/public/uploads/avatar/6755d1936285a.jpg b/public/uploads/avatar/6755d1936285a.jpg new file mode 100644 index 0000000..a53a104 Binary files /dev/null and b/public/uploads/avatar/6755d1936285a.jpg differ diff --git a/public/uploads/avatar/6755d2c6b8d1a.webp b/public/uploads/avatar/6755d2c6b8d1a.webp new file mode 100644 index 0000000..b9ac036 Binary files /dev/null and b/public/uploads/avatar/6755d2c6b8d1a.webp differ diff --git a/public/uploads/avatar/6755d30b21927.webp b/public/uploads/avatar/6755d30b21927.webp new file mode 100644 index 0000000..ac495a0 Binary files /dev/null and b/public/uploads/avatar/6755d30b21927.webp differ diff --git a/public/uploads/avatar/6755d33aa8297.jpg b/public/uploads/avatar/6755d33aa8297.jpg new file mode 100644 index 0000000..b358989 Binary files /dev/null and b/public/uploads/avatar/6755d33aa8297.jpg differ diff --git a/public/uploads/avatar/67573d494838e.jpg b/public/uploads/avatar/67573d494838e.jpg new file mode 100644 index 0000000..a53a104 Binary files /dev/null and b/public/uploads/avatar/67573d494838e.jpg differ diff --git a/public/uploads/avatar/67573d9e340db.webp b/public/uploads/avatar/67573d9e340db.webp new file mode 100644 index 0000000..68f1603 Binary files /dev/null and b/public/uploads/avatar/67573d9e340db.webp differ diff --git a/public/uploads/avatar/67573e27aa9f6.webp b/public/uploads/avatar/67573e27aa9f6.webp new file mode 100644 index 0000000..68f1603 Binary files /dev/null and b/public/uploads/avatar/67573e27aa9f6.webp differ diff --git a/public/uploads/avatar/67573f17ebfb1.webp b/public/uploads/avatar/67573f17ebfb1.webp new file mode 100644 index 0000000..ac495a0 Binary files /dev/null and b/public/uploads/avatar/67573f17ebfb1.webp differ diff --git a/public/uploads/avatar/67573f3773ec9.webp b/public/uploads/avatar/67573f3773ec9.webp new file mode 100644 index 0000000..47d4ccd Binary files /dev/null and b/public/uploads/avatar/67573f3773ec9.webp differ diff --git a/public/uploads/avatar/67573f6dcb273.jpg b/public/uploads/avatar/67573f6dcb273.jpg new file mode 100644 index 0000000..418e165 Binary files /dev/null and b/public/uploads/avatar/67573f6dcb273.jpg differ diff --git a/public/uploads/avatar/67573f8e618d0.webp b/public/uploads/avatar/67573f8e618d0.webp new file mode 100644 index 0000000..8e73520 Binary files /dev/null and b/public/uploads/avatar/67573f8e618d0.webp differ diff --git a/public/uploads/avatar/67573fb157b7c.jpg b/public/uploads/avatar/67573fb157b7c.jpg new file mode 100644 index 0000000..76739ec Binary files /dev/null and b/public/uploads/avatar/67573fb157b7c.jpg differ diff --git a/public/uploads/avatar/67573fc08649b.jpg b/public/uploads/avatar/67573fc08649b.jpg new file mode 100644 index 0000000..fb98385 Binary files /dev/null and b/public/uploads/avatar/67573fc08649b.jpg differ diff --git a/public/uploads/avatar/6757400c07998.jpg b/public/uploads/avatar/6757400c07998.jpg new file mode 100644 index 0000000..f7a455f Binary files /dev/null and b/public/uploads/avatar/6757400c07998.jpg differ diff --git a/public/uploads/avatar/675740139651f.webp b/public/uploads/avatar/675740139651f.webp new file mode 100644 index 0000000..d1709de Binary files /dev/null and b/public/uploads/avatar/675740139651f.webp differ diff --git a/public/uploads/avatar/6757402c16f06.jpg b/public/uploads/avatar/6757402c16f06.jpg new file mode 100644 index 0000000..76739ec Binary files /dev/null and b/public/uploads/avatar/6757402c16f06.jpg differ diff --git a/public/uploads/avatar/675740f397386.jpeg b/public/uploads/avatar/675740f397386.jpeg new file mode 100644 index 0000000..0cd6483 Binary files /dev/null and b/public/uploads/avatar/675740f397386.jpeg differ diff --git a/public/uploads/avatar/675741016fefd.jpg b/public/uploads/avatar/675741016fefd.jpg new file mode 100644 index 0000000..4eb41f7 Binary files /dev/null and b/public/uploads/avatar/675741016fefd.jpg differ diff --git a/public/uploads/avatar/6757443c77760.jpg b/public/uploads/avatar/6757443c77760.jpg new file mode 100644 index 0000000..7b936fd Binary files /dev/null and b/public/uploads/avatar/6757443c77760.jpg differ diff --git a/public/uploads/avatar/67574c62b8e9f.webp b/public/uploads/avatar/67574c62b8e9f.webp new file mode 100644 index 0000000..70d2aba Binary files /dev/null and b/public/uploads/avatar/67574c62b8e9f.webp differ diff --git a/public/uploads/avatar/thumb_6755c5ad0b1fb.jpeg b/public/uploads/avatar/thumb_6755c5ad0b1fb.jpeg new file mode 100644 index 0000000..9dd5dcd Binary files /dev/null and b/public/uploads/avatar/thumb_6755c5ad0b1fb.jpeg differ diff --git a/public/uploads/avatar/thumb_6755c5bc9f6af.jpg b/public/uploads/avatar/thumb_6755c5bc9f6af.jpg new file mode 100644 index 0000000..aa3220e Binary files /dev/null and b/public/uploads/avatar/thumb_6755c5bc9f6af.jpg differ diff --git a/public/uploads/avatar/thumb_6755c5d54e967.jpeg b/public/uploads/avatar/thumb_6755c5d54e967.jpeg new file mode 100644 index 0000000..b59c4a6 Binary files /dev/null and b/public/uploads/avatar/thumb_6755c5d54e967.jpeg differ diff --git a/public/uploads/avatar/thumb_6755c63be9d98.jpg b/public/uploads/avatar/thumb_6755c63be9d98.jpg new file mode 100644 index 0000000..06e0c66 Binary files /dev/null and b/public/uploads/avatar/thumb_6755c63be9d98.jpg differ diff --git a/public/uploads/avatar/thumb_6755cd1809e70.jpg b/public/uploads/avatar/thumb_6755cd1809e70.jpg new file mode 100644 index 0000000..464d7b6 Binary files /dev/null and b/public/uploads/avatar/thumb_6755cd1809e70.jpg differ diff --git a/public/uploads/avatar/thumb_6755cd47262e7.jpg b/public/uploads/avatar/thumb_6755cd47262e7.jpg new file mode 100644 index 0000000..b160a8a Binary files /dev/null and b/public/uploads/avatar/thumb_6755cd47262e7.jpg differ diff --git a/public/uploads/avatar/thumb_6755cded42349.jpg b/public/uploads/avatar/thumb_6755cded42349.jpg new file mode 100644 index 0000000..be7a8f0 Binary files /dev/null and b/public/uploads/avatar/thumb_6755cded42349.jpg differ diff --git a/public/uploads/avatar/thumb_6755ce2851b15.jpeg b/public/uploads/avatar/thumb_6755ce2851b15.jpeg new file mode 100644 index 0000000..c49c52b Binary files /dev/null and b/public/uploads/avatar/thumb_6755ce2851b15.jpeg differ diff --git a/public/uploads/avatar/thumb_6755ce9065632.jpg b/public/uploads/avatar/thumb_6755ce9065632.jpg new file mode 100644 index 0000000..406f494 Binary files /dev/null and b/public/uploads/avatar/thumb_6755ce9065632.jpg differ diff --git a/public/uploads/avatar/thumb_6755ceb7b5b2b.jpg b/public/uploads/avatar/thumb_6755ceb7b5b2b.jpg new file mode 100644 index 0000000..59c5065 Binary files /dev/null and b/public/uploads/avatar/thumb_6755ceb7b5b2b.jpg differ diff --git a/public/uploads/avatar/thumb_6755cf4965e56.jpg b/public/uploads/avatar/thumb_6755cf4965e56.jpg new file mode 100644 index 0000000..c7fb11d Binary files /dev/null and b/public/uploads/avatar/thumb_6755cf4965e56.jpg differ diff --git a/public/uploads/avatar/thumb_6755cf71f0a2e.jpg b/public/uploads/avatar/thumb_6755cf71f0a2e.jpg new file mode 100644 index 0000000..3efa1eb Binary files /dev/null and b/public/uploads/avatar/thumb_6755cf71f0a2e.jpg differ diff --git a/public/uploads/avatar/thumb_6755d03b757e8.jpg b/public/uploads/avatar/thumb_6755d03b757e8.jpg new file mode 100644 index 0000000..e8d348e Binary files /dev/null and b/public/uploads/avatar/thumb_6755d03b757e8.jpg differ diff --git a/public/uploads/avatar/thumb_6755d0f260125.jpg b/public/uploads/avatar/thumb_6755d0f260125.jpg new file mode 100644 index 0000000..0dca2f8 Binary files /dev/null and b/public/uploads/avatar/thumb_6755d0f260125.jpg differ diff --git a/public/uploads/avatar/thumb_6755d1936285a.jpg b/public/uploads/avatar/thumb_6755d1936285a.jpg new file mode 100644 index 0000000..9c3b2be Binary files /dev/null and b/public/uploads/avatar/thumb_6755d1936285a.jpg differ diff --git a/public/uploads/avatar/thumb_6755d2c6b8d1a.webp b/public/uploads/avatar/thumb_6755d2c6b8d1a.webp new file mode 100644 index 0000000..753e67f Binary files /dev/null and b/public/uploads/avatar/thumb_6755d2c6b8d1a.webp differ diff --git a/public/uploads/avatar/thumb_6755d30b21927.webp b/public/uploads/avatar/thumb_6755d30b21927.webp new file mode 100644 index 0000000..f860402 Binary files /dev/null and b/public/uploads/avatar/thumb_6755d30b21927.webp differ diff --git a/public/uploads/avatar/thumb_6755d33aa8297.jpg b/public/uploads/avatar/thumb_6755d33aa8297.jpg new file mode 100644 index 0000000..5a79094 Binary files /dev/null and b/public/uploads/avatar/thumb_6755d33aa8297.jpg differ diff --git a/public/uploads/avatar/thumb_67573d494838e.jpg b/public/uploads/avatar/thumb_67573d494838e.jpg new file mode 100644 index 0000000..9f0a451 Binary files /dev/null and b/public/uploads/avatar/thumb_67573d494838e.jpg differ diff --git a/public/uploads/avatar/thumb_67573d9e340db.webp b/public/uploads/avatar/thumb_67573d9e340db.webp new file mode 100644 index 0000000..cdf98b0 Binary files /dev/null and b/public/uploads/avatar/thumb_67573d9e340db.webp differ diff --git a/public/uploads/avatar/thumb_67573f6dcb273.jpg b/public/uploads/avatar/thumb_67573f6dcb273.jpg new file mode 100644 index 0000000..c97471a Binary files /dev/null and b/public/uploads/avatar/thumb_67573f6dcb273.jpg differ diff --git a/public/uploads/avatar/thumb_67573f8e618d0.webp b/public/uploads/avatar/thumb_67573f8e618d0.webp new file mode 100644 index 0000000..1ac3918 Binary files /dev/null and b/public/uploads/avatar/thumb_67573f8e618d0.webp differ diff --git a/public/uploads/avatar/thumb_67573fb157b7c.jpg b/public/uploads/avatar/thumb_67573fb157b7c.jpg new file mode 100644 index 0000000..5005bbf Binary files /dev/null and b/public/uploads/avatar/thumb_67573fb157b7c.jpg differ diff --git a/public/uploads/avatar/thumb_67573fc08649b.jpg b/public/uploads/avatar/thumb_67573fc08649b.jpg new file mode 100644 index 0000000..9acb2ee Binary files /dev/null and b/public/uploads/avatar/thumb_67573fc08649b.jpg differ diff --git a/public/uploads/avatar/thumb_675740139651f.webp b/public/uploads/avatar/thumb_675740139651f.webp new file mode 100644 index 0000000..04f8d24 Binary files /dev/null and b/public/uploads/avatar/thumb_675740139651f.webp differ diff --git a/public/uploads/avatar/thumb_6757402c16f06.jpg b/public/uploads/avatar/thumb_6757402c16f06.jpg new file mode 100644 index 0000000..97bd5fe Binary files /dev/null and b/public/uploads/avatar/thumb_6757402c16f06.jpg differ diff --git a/public/uploads/avatar/thumb_675741016fefd.jpg b/public/uploads/avatar/thumb_675741016fefd.jpg new file mode 100644 index 0000000..8e614a1 Binary files /dev/null and b/public/uploads/avatar/thumb_675741016fefd.jpg differ diff --git a/public/uploads/avatar/thumb_6757443c77760.jpg b/public/uploads/avatar/thumb_6757443c77760.jpg new file mode 100644 index 0000000..f135646 Binary files /dev/null and b/public/uploads/avatar/thumb_6757443c77760.jpg differ diff --git a/public/uploads/avatar/thumb_67574c62b8e9f.webp b/public/uploads/avatar/thumb_67574c62b8e9f.webp new file mode 100644 index 0000000..5152ce7 Binary files /dev/null and b/public/uploads/avatar/thumb_67574c62b8e9f.webp differ diff --git a/src/Command/InitCommand.php b/src/Command/InitCommand.php index f2f38bc..fb2e1d2 100644 --- a/src/Command/InitCommand.php +++ b/src/Command/InitCommand.php @@ -39,10 +39,19 @@ class InitCommand extends Command $io->text('Initialisation of the app'); $io->text(''); - // Création du compte admin - $io->text('> Création du compte admin'); + // Création d'un company par defaut + $io->text("> Création d'un company par defaut"); + $company = $this->em->getRepository("App\Entity\Company")->findOneBy([], ['id' => 'ASC']); + if (!$company) { + $company = new Company(); + $company->setTitle($this->params->get('appName')); + $this->em->persist($company); + $this->em->flush(); + } + $user = $this->em->getRepository("App\Entity\User")->findOneBy(['username' => 'admin']); if (!$user) { + $io->text('> Création du compte admin par defaut'); $user = new User(); $hashedPassword = $this->passwordHasher->hashPassword( @@ -54,22 +63,13 @@ class InitCommand extends Command $user->setPassword($hashedPassword); $user->setAvatar('medias/avatar/admin.jpg'); $user->setEmail($this->params->get('appNoreply')); + $user->addCompany($company); + $user->setCompany($company); $this->em->persist($user); } $user->setRoles(['ROLE_ADMIN']); $this->em->flush(); - // Création d'un company par defaut - $io->text("> Création d'un company par defaut"); - $nbcompanys = $this->em->getRepository("App\Entity\Company")->count([]); - if (0 == $nbcompanys) { - $company = new Company(); - $company->setTitle($this->params->get('appName')); - $company->setLogo('logo.png'); - $this->em->persist($company); - $this->em->flush(); - } - return Command::SUCCESS; } } diff --git a/src/Controller/AccountingController.php b/src/Controller/AccountingController.php new file mode 100644 index 0000000..6fa62a7 --- /dev/null +++ b/src/Controller/AccountingController.php @@ -0,0 +1,108 @@ +getSession()->get('company'); + $accountings = $accountingRepository->findBy(['company' => $company], ['num01' => 'ASC', 'num02' => 'ASC']); + + return $this->render('accounting/list.html.twig', [ + 'usemenu' => true, + 'usesidebar' => true, + 'title' => 'Plan Comptable', + 'routesubmit' => 'app_user_accounting_submit', + 'routeupdate' => 'app_user_accounting_update', + 'accountings' => $accountings, + ]); + } + + #[Route('/user/accounting/submit', name: 'app_user_accounting_submit')] + public function submit(Request $request, EntityManagerInterface $em): Response + { + $company = $request->getSession()->get('company'); + $accounting = new Accounting(); + $accounting->setCompany($company); + + $form = $this->createForm(AccountingType::class, $accounting, ['mode' => 'submit']); + $form->handleRequest($request); + if ($form->isSubmitted() && $form->isValid()) { + $em->persist($accounting); + $em->flush(); + + return $this->redirectToRoute('app_user_accounting'); + } + + return $this->render('accounting/edit.html.twig', [ + 'usemenu' => true, + 'usesidebar' => true, + 'title' => 'Création Compagnie', + 'routecancel' => 'app_user_accounting', + 'routedelete' => 'app_user_accounting_delete', + 'mode' => 'submit', + 'form' => $form, + ]); + } + + #[Route('/user/accounting/update/{id}', name: 'app_user_accounting_update')] + public function update(int $id, Request $request, EntityManagerInterface $em): Response + { + $company = $request->getSession()->get('company'); + $accounting = $em->getRepository(Accounting::class)->find($id); + if (!$accounting || $accounting->getCompany() != $company) { + return $this->redirectToRoute('app_user_accounting'); + } + + $form = $this->createForm(AccountingType::class, $accounting, ['mode' => 'update']); + $form->handleRequest($request); + if ($form->isSubmitted() && $form->isValid()) { + $em->flush(); + + return $this->redirectToRoute('app_user_accounting'); + } + + return $this->render('accounting/edit.html.twig', [ + 'usemenu' => true, + 'usesidebar' => true, + 'title' => 'Modification Compagnie = '.$accounting->getTitle(), + 'routecancel' => 'app_user_accounting', + 'routedelete' => 'app_user_accounting_delete', + 'mode' => 'update', + 'form' => $form, + ]); + } + + #[Route('/user/accounting/delete/{id}', name: 'app_user_accounting_delete')] + public function delete(int $id, Request $request, EntityManagerInterface $em): Response + { + $company = $request->getSession()->get('company'); + $accounting = $em->getRepository(Accounting::class)->find($id); + if (!$accounting || $accounting->getCompany() != $company) { + return $this->redirectToRoute('app_user_accounting'); + } + + // Tentative de suppression + try { + $em->remove($accounting); + $em->flush(); + } catch (\Exception $e) { + $this->addflash('error', $e->getMessage()); + + return $this->redirectToRoute('app_user_accounting_update', ['id' => $id]); + } + + return $this->redirectToRoute('app_user_accounting'); + } +} diff --git a/src/Controller/CompanyController.php b/src/Controller/CompanyController.php index 1e70ee8..cab5395 100644 --- a/src/Controller/CompanyController.php +++ b/src/Controller/CompanyController.php @@ -2,17 +2,103 @@ namespace App\Controller; +use App\Entity\Company; +use App\Form\CompanyType; +use App\Repository\CompanyRepository; +use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; class CompanyController extends AbstractController { - #[Route('/admin/company', name: 'app_company')] - public function index(): Response + #[Route('/admin/company', name: 'app_admin_company')] + public function list(CompanyRepository $companyRepository): Response { - return $this->render('company/index.html.twig', [ - 'controller_name' => 'CompanyController', + $companys = $companyRepository->findAll(); + + return $this->render('company/list.html.twig', [ + 'usemenu' => true, + 'usesidebar' => true, + 'title' => 'Liste des Compagnies', + 'routesubmit' => 'app_admin_company_submit', + 'routeupdate' => 'app_admin_company_update', + 'companys' => $companys, ]); } + + #[Route('/admin/company/submit', name: 'app_admin_company_submit')] + public function submit(Request $request, EntityManagerInterface $em): Response + { + $company = new Company(); + + $form = $this->createForm(CompanyType::class, $company, ['mode' => 'submit']); + $form->handleRequest($request); + if ($form->isSubmitted() && $form->isValid()) { + $em->persist($company); + $em->flush(); + + return $this->redirectToRoute('app_admin_company'); + } + + return $this->render('company/edit.html.twig', [ + 'usemenu' => true, + 'usesidebar' => true, + 'title' => 'Création Compagnie', + 'routecancel' => 'app_admin_company', + 'routedelete' => 'app_admin_company_delete', + 'mode' => 'submit', + 'form' => $form, + ]); + } + + #[Route('/admin/company/update/{id}', name: 'app_admin_company_update')] + public function update(int $id, Request $request, EntityManagerInterface $em): Response + { + $company = $em->getRepository(Company::class)->find($id); + if (!$company) { + return $this->redirectToRoute('app_admin_company'); + } + + $form = $this->createForm(CompanyType::class, $company, ['mode' => 'update']); + $form->handleRequest($request); + if ($form->isSubmitted() && $form->isValid()) { + $em->flush(); + + return $this->redirectToRoute('app_admin_user'); + } + + return $this->render('company/edit.html.twig', [ + 'usemenu' => true, + 'usesidebar' => true, + 'title' => 'Modification Compagnie = '.$company->getTitle(), + 'routecancel' => 'app_admin_company', + 'routedelete' => 'app_admin_company_delete', + 'mode' => 'update', + 'form' => $form, + ]); + } + + #[Route('/admin/company/delete/{id}', name: 'app_admin_company_delete')] + public function delete(int $id, EntityManagerInterface $em): Response + { + // Récupération de l'enregistrement courant + $company = $em->getRepository(Company::class)->find($id); + if (!$company) { + return $this->redirectToRoute('app_admin_company'); + } + + // Tentative de suppression + try { + $em->remove($company); + $em->flush(); + } catch (\Exception $e) { + $this->addflash('error', $e->getMessage()); + + return $this->redirectToRoute('app_admin_company_update', ['id' => $id]); + } + + return $this->redirectToRoute('app_admin_company'); + } } diff --git a/src/Controller/CropController.php b/src/Controller/CropController.php deleted file mode 100644 index cab6eaa..0000000 --- a/src/Controller/CropController.php +++ /dev/null @@ -1,31 +0,0 @@ -render('crop\crop01.html.twig', [ - 'useheader' => false, - 'usemenu' => false, - 'usesidebar' => false, - 'endpoint' => $endpoint, - ]); - } - - #[Route('/user/crop02', name: 'app_user_crop02')] - public function crop02(): Response - { - return $this->render('crop\crop01.html.twig', [ - 'useheader' => false, - 'usemenu' => false, - 'usesidebar' => false, - ]); - } -} diff --git a/src/Controller/HomeController.php b/src/Controller/HomeController.php index cfe9670..1e90033 100644 --- a/src/Controller/HomeController.php +++ b/src/Controller/HomeController.php @@ -2,18 +2,24 @@ namespace App\Controller; +use App\Repository\AccountingRepository; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; class HomeController extends AbstractController { #[Route('/', name: 'app_home')] - public function home(): Response + public function home(Request $request, AccountingRepository $accountingRepository): Response { + $company = $request->getSession()->get('company'); + $accountings = $accountingRepository->findBy(['company' => $company, 'category' => 'actif'], ['num01' => 'ASC', 'num02' => 'ASC']); + return $this->render('home/home.html.twig', [ 'usemenu' => true, 'usesidebar' => false, + 'accountings' => $accountings, ]); } @@ -25,4 +31,13 @@ class HomeController extends AbstractController 'usesidebar' => true, ]); } + + #[Route('/user/nocompany', name: 'app_user_nocompany')] + public function nocompany(): Response + { + return $this->render('home/nocompany.html.twig', [ + 'usemenu' => true, + 'usesidebar' => false, + ]); + } } diff --git a/src/Controller/UploadController.php b/src/Controller/UploadController.php new file mode 100644 index 0000000..bcd143b --- /dev/null +++ b/src/Controller/UploadController.php @@ -0,0 +1,81 @@ +imageService = $imageService; + } + + #[Route('/user/upload/crop01/{endpoint}', name: 'app_user_upload_crop01')] + public function crop01(string $endpoint, Request $request): Response + { + $reportThumb = $request->get('reportThumb'); + + return $this->render('upload\crop01.html.twig', [ + 'useheader' => false, + 'usemenu' => false, + 'usesidebar' => false, + 'endpoint' => $endpoint, + 'reportThumb' => $reportThumb, + ]); + } + + #[Route('/user/upload/crop02', name: 'app_user_upload_crop02')] + public function crop02(Request $request): Response + { + $reportThumb = $request->get('reportThumb'); + $path = $request->get('path'); + $file = $request->get('file'); + $image = $this->getParameter('kernel.project_dir').'/public/'.$path.'/'.$file; + $thumb = $this->getParameter('kernel.project_dir').'/public/'.$path.'/thumb_'.$file; + + // Redimentionner + $this->imageService->resizeImage($image, 700, 700); + + // Construction du formulaire + $form = $this->createFormBuilder() + ->add('submit', SubmitType::class, ['label' => 'Valider', 'attr' => ['class' => 'btn btn-success']]) + ->add('x1', HiddenType::class) + ->add('y1', HiddenType::class) + ->add('x2', HiddenType::class) + ->add('y2', HiddenType::class) + ->add('w', HiddenType::class) + ->add('h', HiddenType::class) + ->getForm(); + + // Récupération des data du formulaire + $form->handleRequest($request); + $toReport = false; + // Sur validation on généère la miniature croppée + if ($form->isSubmitted() && $form->isValid()) { + $data = $form->getData(); + $toReport = true; + dump($data); + $this->imageService->cropImage($image, $thumb, $data['x1'], $data['y1'], $data['w'], $data['h'], 150, 150); + } + + return $this->render('upload\crop02.html.twig', [ + 'useheader' => false, + 'usemenu' => false, + 'usesidebar' => false, + 'reportThumb' => $reportThumb, + 'image' => $path.'/'.$file, + 'thumb' => $path.'/thumb_'.$file, + 'form' => $form, + 'toReport' => $toReport, + ]); + } +} diff --git a/src/Controller/UserController.php b/src/Controller/UserController.php index 6863ead..25d72b6 100644 --- a/src/Controller/UserController.php +++ b/src/Controller/UserController.php @@ -2,11 +2,13 @@ namespace App\Controller; +use App\Entity\Company; use App\Entity\User; use App\Form\UserType; use App\Repository\UserRepository; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface; @@ -69,7 +71,6 @@ class UserController extends AbstractController return $this->redirectToRoute('app_admin_user'); } $hashedPassword = $user->getPassword(); - $user->setPassword(''); $form = $this->createForm(UserType::class, $user, ['mode' => 'update']); $form->handleRequest($request); @@ -82,8 +83,6 @@ class UserController extends AbstractController ); } $user->setPassword($hashedPassword); - - $em->persist($user); $em->flush(); return $this->redirectToRoute('app_admin_user'); @@ -101,14 +100,87 @@ class UserController extends AbstractController } #[Route('/admin/user/delete/{id}', name: 'app_admin_user_delete')] - public function delete(int $id): Response + public function delete(int $id, EntityManagerInterface $em): Response { + $user = $em->getRepository(User::class)->find($id); + if (!$user) { + return $this->redirectToRoute('app_admin_user'); + } + + // Tentative de suppression + try { + $em->remove($user); + $em->flush(); + } catch (\Exception $e) { + $this->addflash('error', $e->getMessage()); + + return $this->redirectToRoute('app_admin_user_update', ['id' => $id]); + } + return $this->redirectToRoute('app_admin_user'); } #[Route('/user', name: 'app_user_profil')] - public function profil(): Response + public function profil(Request $request, UserPasswordHasherInterface $passwordHasher, EntityManagerInterface $em): Response { - return $this->redirectToRoute('app_home'); + $user = $em->getRepository(User::class)->find($this->getUser()); + if (!$user) { + return $this->redirectToRoute('app_home'); + } + $hashedPassword = $user->getPassword(); + + $form = $this->createForm(UserType::class, $user, ['mode' => 'profil']); + $form->handleRequest($request); + if ($form->isSubmitted() && $form->isValid()) { + $user = $form->getData(); + if ($user->getPassword()) { + $hashedPassword = $passwordHasher->hashPassword( + $user, + $user->getPassword() + ); + } + $user->setPassword($hashedPassword); + + $em->persist($user); + $em->flush(); + + return $this->redirectToRoute('app_home'); + } + + return $this->render('user/edit.html.twig', [ + 'usemenu' => true, + 'usesidebar' => false, + 'title' => 'Profil = '.$user->getUsername(), + 'routecancel' => 'app_home', + 'routedelete' => '', + 'mode' => 'profil', + 'form' => $form, + ]); + } + + #[Route('/admin/user/selectcompany', name: 'app_user_selectcompany')] + public function selectcompany(Request $request, EntityManagerInterface $em): JsonResponse + { + $id = $request->get('id'); + + $company = $em->getRepository(Company::class)->find($id); + if (!$company) { + return new JsonResponse(['status' => 'KO', 'message' => 'ID non fourni'], Response::HTTP_NOT_FOUND); + } + + $user = $this->getUser(); + if (!$user instanceof User) { + throw new \LogicException('L\'utilisateur actuel n\'est pas une instance de App\Entity\User.'); + } + + $companys = $user->getCompanys(); + if (!$companys->contains($company)) { + return new JsonResponse(['status' => 'KO', 'message' => 'Compangnie non autorisée'], Response::HTTP_FORBIDDEN); + } + + $user->setCompany($company); + $em->flush(); + + return new JsonResponse(['status' => 'OK', 'message' => 'Compangnie selectionnée'], Response::HTTP_OK); } } diff --git a/src/Entity/Accounting.php b/src/Entity/Accounting.php index 3310a73..87df314 100644 --- a/src/Entity/Accounting.php +++ b/src/Entity/Accounting.php @@ -7,10 +7,11 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; +use Symfony\Component\Validator\Constraints as Assert; #[ORM\Entity(repositoryClass: AccountingRepository::class)] -#[ORM\UniqueConstraint(name: 'UNIQ_IDENTIFIER_ACCOUNTING', fields: ['num01', 'num02'])] -#[UniqueEntity(fields: ['num01', 'num02'], message: 'Ce numéro de compte est déjà utilisé.')] +#[ORM\UniqueConstraint(name: 'UNIQ_IDENTIFIER_ACCOUNTING', fields: ['company', 'num01', 'num02'])] +#[UniqueEntity(fields: ['company', 'num01', 'num02'], message: 'Ce numéro de compte est déjà utilisé.')] class Accounting { #[ORM\Id] @@ -18,10 +19,18 @@ class Accounting #[ORM\Column] private ?int $id = null; - #[ORM\Column(length: 255)] + #[ORM\Column(length: 3)] + #[Assert\Regex( + pattern: '/^[0-9]{3}$/', + message: 'La valeur doit être un nombre de trois chiffres (ex: 001, 098, 540).' + )] private ?string $num01 = null; - #[ORM\Column(length: 255)] + #[ORM\Column(length: 10)] + #[Assert\Regex( + pattern: '/^[0-9]{3}$/', + message: 'La valeur doit être un nombre de trois chiffres (ex: 001, 098, 540).' + )] private ?string $num02 = null; #[ORM\Column(length: 255)] @@ -67,7 +76,7 @@ class Accounting public function setNum01(string $num01): static { - $this->num01 = $num01; + $this->num01 = str_pad($num01, 3, '0', STR_PAD_LEFT); return $this; } @@ -79,7 +88,7 @@ class Accounting public function setNum02(string $num02): static { - $this->num02 = $num02; + $this->num02 = str_pad($num02, 3, '0', STR_PAD_LEFT); return $this; } diff --git a/src/Entity/Company.php b/src/Entity/Company.php index 6dc566e..c6b24db 100644 --- a/src/Entity/Company.php +++ b/src/Entity/Company.php @@ -8,6 +8,7 @@ use Doctrine\Common\Collections\Collection; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; +use Symfony\Component\Validator\Constraints as Assert; #[ORM\Entity(repositoryClass: CompanyRepository::class)] #[ORM\UniqueConstraint(name: 'UNIQ_IDENTIFIER_COMPANY', fields: ['title'])] @@ -22,12 +23,16 @@ class Company #[ORM\Column(length: 255, unique: true)] private ?string $title = null; - #[ORM\Column(type: Types::TEXT, nullable: true)] - private ?string $adress = null; - #[ORM\Column(length: 255, nullable: true)] private ?string $logo = null; + #[ORM\Column(length: 255, nullable: true)] + #[Assert\Email(message: 'Veuillez entrer un email valide.')] + private ?string $email = null; + + #[ORM\Column(type: Types::TEXT, nullable: true)] + private ?string $adress = null; + #[ORM\Column(length: 255, nullable: true)] private ?string $bankname = null; @@ -87,6 +92,30 @@ class Company return $this; } + public function getLogo(): ?string + { + return $this->logo ? $this->logo : 'medias/logo/logo.png'; + } + + public function setLogo(?string $logo): static + { + $this->logo = $logo; + + return $this; + } + + public function getEmail(): ?string + { + return $this->email; + } + + public function setEmail(?string $email): static + { + $this->email = $email; + + return $this; + } + public function getAdress(): ?string { return $this->adress; @@ -99,18 +128,6 @@ class Company return $this; } - public function getLogo(): ?string - { - return $this->logo; - } - - public function setLogo(?string $logo): static - { - $this->logo = $logo; - - return $this; - } - public function getBankname(): ?string { return $this->bankname; diff --git a/src/Entity/User.php b/src/Entity/User.php index ef2f3ab..d7180d1 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -46,6 +46,10 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface #[ORM\ManyToMany(targetEntity: Company::class, inversedBy: 'users')] private Collection $companys; + #[ORM\ManyToOne()] + #[ORM\JoinColumn(nullable: true)] + private ?Company $company = null; + public function __construct() { $this->companys = new ArrayCollection(); @@ -173,4 +177,20 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface return $this; } + + public function getCompany(): ?Company + { + if (!$this->companys) { + return null; + } + + return $this->company; + } + + public function setCompany(?Company $company): static + { + $this->company = $company; + + return $this; + } } diff --git a/src/EventListener/SessionListener.php b/src/EventListener/SessionListener.php new file mode 100644 index 0000000..6eab6cf --- /dev/null +++ b/src/EventListener/SessionListener.php @@ -0,0 +1,47 @@ +security = $security; + $this->router = $router; + } + + #[AsEventListener(event: KernelEvents::REQUEST)] + public function onKernelRequest(RequestEvent $event): void + { + $request = $event->getRequest(); + $session = $request->getSession(); + + $user = $this->security->getUser(); + if ($user instanceof User && $user) { + // Intialisation de la compagnie en cours + if (!$user->getCompany()) { + if ($user->getCompanys()) { + $user->setCompany($user->getCompanys()[0]); + } + } + + $session->set('company', $user->getCompany()); + $session->set('companys', $user->getCompanys()); + + if (!$user->getCompany()) { + $event->setResponse(new RedirectResponse($this->router->generate('app_user_nocompany', []))); + } + } + } +} diff --git a/src/EventListener/UploadListener.php b/src/EventListener/UploadListener.php new file mode 100644 index 0000000..2e52502 --- /dev/null +++ b/src/EventListener/UploadListener.php @@ -0,0 +1,41 @@ +projectDir = $kernel->getProjectDir(); + } + + #[AsEventListener(event: 'oneup_uploader.validation')] + public function onOneupUploaderValidation(ValidationEvent $event): void + { + // On s'assure que le repertoire de destination existe bien + $fs = new Filesystem(); + $fs->mkdir($this->projectDir.'/public/uploads'); + $fs->mkdir($this->projectDir.'/public/uploads/'.$event->getType()); + } + + #[AsEventListener(event: 'oneup_uploader.post_persist')] + public function onOneupUploaderPostPersit(PostPersistEvent $event): void + { + $file = $event->getFile(); + $type = $event->getType(); + $filename = $file->getFilename(); + $response = $event->getResponse(); + $response['file'] = $filename; + $response['path'] = 'uploads/'.$type; + $response['filepath'] = 'uploads/'.$type.'/'.$filename; + } +} diff --git a/src/Form/AccountingType.php b/src/Form/AccountingType.php new file mode 100644 index 0000000..437a9e6 --- /dev/null +++ b/src/Form/AccountingType.php @@ -0,0 +1,62 @@ +threeDigitTransformer = $threeDigitTransformer; + } + + public function buildForm(FormBuilderInterface $builder, array $options): void + { + $builder + ->add('submit', SubmitType::class, [ + 'label' => 'Valider', + 'attr' => ['class' => 'btn btn-success no-print'], + ]) + + ->add('num01', ThreeDigitType::class, [ + 'label' => 'Numéro de Compte 01', + ]) + + ->add('num02', ThreeDigitType::class, [ + 'label' => 'Numéro de Compte 01', + ]) + + ->add('title', TextType::class, [ + 'label' => 'Titre', + ]) + + ->add('category', ChoiceType::class, [ + 'label' => 'Catégorie', + 'choices' => ['passif' => 'passif', 'actif' => 'actif', 'charge' => 'charge', 'produit' => 'produit'], + ]) + + ->add('icon', FontawsomeType::class, [ + 'label' => 'Icône', + 'attr' => ['class' => 'select2'], + ]); + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => Accounting::class, + 'mode' => 'submit', + ]); + } +} diff --git a/src/Form/CompanyType.php b/src/Form/CompanyType.php new file mode 100644 index 0000000..5a3bf44 --- /dev/null +++ b/src/Form/CompanyType.php @@ -0,0 +1,91 @@ +add('submit', SubmitType::class, [ + 'label' => 'Valider', + 'attr' => ['class' => 'btn btn-success no-print'], + ]) + + ->add('title', TextType::class, [ + 'label' => 'Nom', + ]) + + ->add('email', EmailType::class, [ + 'label' => 'Email', + 'required' => false, + ]) + + ->add('logo', HiddenType::class) + + ->add('adress', TextType::class, [ + 'label' => 'Adresse', + 'required' => false, + ]) + + ->add('bankname', TextType::class, [ + 'required' => false, + ]) + + ->add('bankcode', TextType::class, [ + 'required' => false, + ]) + + ->add('bankguichet', TextType::class, [ + 'required' => false, + ]) + + ->add('banknum', TextType::class, [ + 'required' => false, + ]) + + ->add('bankkey', TextType::class, [ + 'required' => false, + ]) + + ->add('banklocality', TextType::class, [ + 'required' => false, + ]) + + ->add('bankiban', TextType::class, [ + 'required' => false, + ]) + + ->add('bankbic', TextType::class, [ + 'required' => false, + ]) + + ->add('users', EntityType::class, [ + 'label' => 'Utilisateurs', + 'class' => User::class, + 'choice_label' => 'username', + 'multiple' => true, + 'attr' => ['class' => 'select2'], + 'required' => false, + ]); + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => Company::class, + 'mode' => 'submit', + ]); + } +} diff --git a/src/Form/DataTransformer/ThreeDigitTransformer.php b/src/Form/DataTransformer/ThreeDigitTransformer.php new file mode 100644 index 0000000..8925735 --- /dev/null +++ b/src/Form/DataTransformer/ThreeDigitTransformer.php @@ -0,0 +1,18 @@ +setDefaults([ + 'choices' => $this->getFontAwesomeIcons(), + ]); + } + + public function getParent(): string + { + return ChoiceType::class; + } + + private function getFontAwesomeIcons(): array + { + $icons = [ + 'ad', + 'address-book', + 'address-card', + 'adjust', + 'air-freshener', + 'align-center', + 'align-justify', + 'align-left', + 'align-right', + 'allergies', + 'ambulance', + 'american-sign-language-interpreting', + 'anchor', + 'angle-double-down', + 'angle-double-left', + 'angle-double-right', + 'angle-double-up', + 'angle-down', + 'angle-left', + 'angle-right', + 'angle-up', + 'angry', + 'ankh', + 'apple-alt', + 'archive', + 'archway', + 'arrow-alt-circle-down', + 'arrow-alt-circle-left', + 'arrow-alt-circle-right', + 'arrow-alt-circle-up', + 'arrow-circle-down', + 'arrow-circle-left', + 'arrow-circle-right', + 'arrow-circle-up', + 'arrow-down', + 'arrow-left', + 'arrow-right', + 'arrow-up', + 'arrows-alt', + 'arrows-alt-h', + 'arrows-alt-v', + 'assistive-listening-systems', + 'asterisk', + 'at', + 'atlas', + 'atom', + 'audio-description', + 'award', + 'baby', + 'baby-carriage', + 'backspace', + 'backward', + 'bacon', + 'bahai', + 'balance-scale', + 'balance-scale-left', + 'balance-scale-right', + 'ban', + 'band-aid', + 'barcode', + 'bars', + 'baseball-ball', + 'basketball-ball', + 'bath', + 'battery-empty', + 'battery-full', + 'battery-half', + 'battery-quarter', + 'battery-three-quarters', + 'bed', + 'beer', + 'bell', + 'bell-slash', + 'bezier-curve', + 'bible', + 'bicycle', + 'biking', + 'binoculars', + 'biohazard', + 'birthday-cake', + 'blender', + 'blender-phone', + 'blind', + 'blog', + 'bold', + 'bolt', + 'bomb', + 'bone', + 'bong', + 'book', + 'book-dead', + 'book-medical', + 'book-open', + 'book-reader', + 'bookmark', + 'border-all', + 'border-none', + 'border-style', + 'bowling-ball', + 'box', + 'box-open', + 'boxes', + 'braille', + 'brain', + 'bread-slice', + 'briefcase', + 'briefcase-medical', + 'broadcast-tower', + 'broom', + 'brush', + 'bug', + 'building', + 'bullhorn', + 'bullseye', + 'burn', + 'bus', + 'bus-alt', + 'business-time', + 'calculator', + 'calendar', + 'calendar-alt', + 'calendar-check', + 'calendar-day', + 'calendar-minus', + 'calendar-plus', + 'calendar-times', + 'calendar-week', + 'camera', + 'camera-retro', + 'campground', + 'candy-cane', + 'cannabis', + 'capsules', + 'car', + 'car-alt', + 'car-battery', + 'car-crash', + 'car-side', + 'caravan', + 'caret-down', + 'caret-left', + 'caret-right', + 'caret-square-down', + 'caret-square-left', + 'caret-square-right', + 'caret-square-up', + 'caret-up', + 'carrot', + 'cart-arrow-down', + 'cart-plus', + 'cash-register', + 'cat', + 'certificate', + 'chair', + 'chalkboard', + 'chalkboard-teacher', + 'charging-station', + 'chart-area', + 'chart-bar', + 'chart-line', + 'chart-pie', + 'check', + 'check-circle', + 'check-double', + 'check-square', + 'cheese', + 'chess', + 'chess-bishop', + 'chess-board', + 'chess-king', + 'chess-knight', + 'chess-pawn', + 'chess-queen', + 'chess-rook', + 'chevron-circle-down', + 'chevron-circle-left', + 'chevron-circle-right', + 'chevron-circle-up', + 'chevron-down', + 'chevron-left', + 'chevron-right', + 'chevron-up', + 'child', + 'church', + 'circle', + 'circle-notch', + 'city', + 'clinic-medical', + 'clipboard', + 'clipboard-check', + 'clipboard-list', + 'clock', + 'clone', + 'closed-captioning', + 'cloud', + 'cloud-download-alt', + 'cloud-meatball', + 'cloud-moon', + 'cloud-moon-rain', + 'cloud-rain', + 'cloud-showers-heavy', + 'cloud-sun', + 'cloud-sun-rain', + 'cloud-upload-alt', + 'cocktail', + 'code', + 'code-branch', + 'coffee', + 'cog', + 'cogs', + 'coins', + 'columns', + 'comment', + 'comment-alt', + 'comment-dollar', + 'comment-dots', + 'comment-medical', + 'comment-slash', + 'comments', + 'comments-dollar', + 'compact-disc', + 'compass', + 'compress', + 'compress-alt', + 'compress-arrows-alt', + 'concierge-bell', + 'cookie', + 'cookie-bite', + 'copy', + 'copyright', + 'couch', + 'credit-card', + 'crop', + 'crop-alt', + 'cross', + 'crosshairs', + 'crow', + 'crown', + 'crutch', + 'cube', + 'cubes', + 'cut', + 'database', + 'deaf', + 'democrat', + 'desktop', + 'dharmachakra', + 'diagnoses', + 'dice', + 'dice-d20', + 'dice-d6', + 'dice-five', + 'dice-four', + 'dice-one', + 'dice-six', + 'dice-three', + 'dice-two', + 'digital-tachograph', + 'directions', + 'divide', + 'dizzy', + 'dna', + 'dog', + 'dollar-sign', + 'dolly', + 'dolly-flatbed', + 'donate', + 'door-closed', + 'door-open', + 'dot-circle', + 'dove', + 'download', + 'drafting-compass', + 'dragon', + 'draw-polygon', + 'drum', + 'drum-steelpan', + 'drumstick-bite', + 'dumbbell', + 'dumpster', + 'dumpster-fire', + 'dungeon', + 'edit', + 'egg', + 'eject', + 'ellipsis-h', + 'ellipsis-v', + 'envelope', + 'envelope-open', + 'envelope-open-text', + 'envelope-square', + 'equals', + 'eraser', + 'ethernet', + 'euro-sign', + 'exchange-alt', + 'exclamation', + 'exclamation-circle', + 'exclamation-triangle', + 'expand', + 'expand-alt', + 'expand-arrows-alt', + 'external-link-alt', + 'external-link-square-alt', + 'eye', + 'eye-dropper', + 'eye-slash', + 'fan', + 'fast-backward', + 'fast-forward', + 'fax', + 'feather', + 'feather-alt', + 'female', + 'fighter-jet', + 'file', + 'file-alt', + 'file-archive', + 'file-audio', + 'file-code', + 'file-contract', + 'file-csv', + 'file-download', + 'file-excel', + 'file-export', + 'file-image', + 'file-import', + 'file-invoice', + 'file-invoice-dollar', + 'file-medical', + 'file-medical-alt', + 'file-pdf', + 'file-powerpoint', + 'file-prescription', + 'file-signature', + 'file-upload', + 'file-video', + 'file-word', + 'fill', + 'fill-drip', + 'film', + 'filter', + 'fingerprint', + 'fire', + 'fire-alt', + 'fire-extinguisher', + 'first-aid', + 'fish', + 'fist-raised', + 'flag', + 'flag-checkered', + 'flag-usa', + 'flask', + 'flushed', + 'folder', + 'folder-minus', + 'folder-open', + 'folder-plus', + 'font', + 'football-ball', + 'forward', + 'frog', + 'frown', + 'frown-open', + 'funnel-dollar', + 'futbol', + 'gamepad', + 'gas-pump', + 'gavel', + 'gem', + 'genderless', + 'ghost', + 'gift', + 'gifts', + 'glass-cheers', + 'glass-martini', + 'glass-martini-alt', + 'glass-whiskey', + 'glasses', + 'globe', + 'globe-africa', + 'globe-americas', + 'globe-asia', + 'globe-europe', + 'golf-ball', + 'gopuram', + 'graduation-cap', + 'greater-than', + 'greater-than-equal', + 'grimace', + 'grin', + 'grin-alt', + 'grin-beam', + 'grin-beam-sweat', + 'grin-hearts', + 'grin-squint', + 'grin-squint-tears', + 'grin-stars', + 'grin-tears', + 'grin-tongue', + 'grin-tongue-squint', + 'grin-tongue-wink', + 'grin-wink', + 'grip-horizontal', + 'grip-lines', + 'grip-lines-vertical', + 'grip-vertical', + 'guitar', + 'h-square', + 'hamburger', + 'hammer', + 'hamsa', + 'hand-holding', + 'hand-holding-heart', + 'hand-holding-usd', + 'hand-lizard', + 'hand-middle-finger', + 'hand-paper', + 'hand-peace', + 'hand-point-down', + 'hand-point-left', + 'hand-point-right', + 'hand-point-up', + 'hand-pointer', + 'hand-rock', + 'hand-scissors', + 'hand-spock', + 'hands', + 'hands-helping', + 'handshake', + 'hanukiah', + 'hard-hat', + 'hashtag', + 'hat-cowboy', + 'hat-cowboy-side', + 'hat-wizard', + 'hdd', + 'heading', + 'headphones', + 'headphones-alt', + 'headset', + 'heart', + 'heart-broken', + 'heartbeat', + 'helicopter', + 'highlighter', + 'hiking', + 'hippo', + 'history', + 'hockey-puck', + 'holly-berry', + 'home', + 'horse', + 'horse-head', + 'hospital', + 'hospital-alt', + 'hospital-symbol', + 'hot-tub', + 'hotdog', + 'hotel', + 'hourglass', + 'hourglass-end', + 'hourglass-half', + 'hourglass-start', + 'house-damage', + 'hryvnia', + 'i-cursor', + 'ice-cream', + 'icicles', + 'icons', + 'id-badge', + 'id-card', + 'id-card-alt', + 'igloo', + 'image', + 'images', + 'inbox', + 'indent', + 'industry', + 'infinity', + 'info', + 'info-circle', + 'italic', + 'jedi', + 'joint', + 'journal-whills', + 'kaaba', + 'key', + 'keyboard', + 'khanda', + 'kiss', + 'kiss-beam', + 'kiss-wink-heart', + 'kiwi-bird', + 'landmark', + 'language', + 'laptop', + 'laptop-code', + 'laptop-medical', + 'laugh', + 'laugh-beam', + 'laugh-squint', + 'laugh-wink', + 'layer-group', + 'leaf', + 'lemon', + 'less-than', + 'less-than-equal', + 'level-down-alt', + 'level-up-alt', + 'life-ring', + 'lightbulb', + 'link', + 'lira-sign', + 'list', + 'list-alt', + 'list-ol', + 'list-ul', + 'location-arrow', + 'lock', + 'lock-open', + 'long-arrow-alt-down', + 'long-arrow-alt-left', + 'long-arrow-alt-right', + 'long-arrow-alt-up', + 'low-vision', + 'luggage-cart', + 'magic', + 'magnet', + 'mail-bulk', + 'male', + 'map', + 'map-marked', + 'map-marked-alt', + 'map-marker', + 'map-marker-alt', + 'map-pin', + 'map-signs', + 'marker', + 'mars', + 'mars-double', + 'mars-stroke', + 'mars-stroke-h', + 'mars-stroke-v', + 'mask', + 'medal', + 'medkit', + 'meh', + 'meh-blank', + 'meh-rolling-eyes', + 'memory', + 'menorah', + 'mercury', + 'meteor', + 'microchip', + 'microphone', + 'microphone-alt', + 'microphone-alt-slash', + 'microphone-slash', + 'microscope', + 'minus', + 'minus-circle', + 'minus-square', + 'mitten', + 'mobile', + 'mobile-alt', + 'money-bill', + 'money-bill-alt', + 'money-bill-wave', + 'money-bill-wave-alt', + 'money-check', + 'money-check-alt', + 'monument', + 'moon', + 'mortar-pestle', + 'mosque', + 'motorcycle', + 'mountain', + 'mouse', + 'mouse-pointer', + 'mug-hot', + 'music', + 'network-wired', + 'neuter', + 'newspaper', + 'not-equal', + 'notes-medical', + 'object-group', + 'object-ungroup', + 'oil-can', + 'om', + 'otter', + 'outdent', + 'pager', + 'paint-brush', + 'paint-roller', + 'palette', + 'pallet', + 'paper-plane', + 'paperclip', + 'parachute-box', + 'paragraph', + 'parking', + 'passport', + 'pastafarianism', + 'paste', + 'pause', + 'pause-circle', + 'paw', + 'peace', + 'pen', + 'pen-alt', + 'pen-fancy', + 'pen-nib', + 'pen-square', + 'pencil-alt', + 'pencil-ruler', + 'people-carry', + 'pepper-hot', + 'percent', + 'percentage', + 'person-booth', + 'phone', + 'phone-alt', + 'phone-slash', + 'phone-square', + 'phone-square-alt', + 'phone-volume', + 'photo-video', + 'piggy-bank', + 'pills', + 'pizza-slice', + 'place-of-worship', + 'plane', + 'plane-arrival', + 'plane-departure', + 'play', + 'play-circle', + 'plug', + 'plus', + 'plus-circle', + 'plus-square', + 'podcast', + 'poll', + 'poll-h', + 'poo', + 'poo-storm', + 'poop', + 'portrait', + 'pound-sign', + 'power-off', + 'pray', + 'praying-hands', + 'prescription', + 'prescription-bottle', + 'prescription-bottle-alt', + 'print', + 'procedures', + 'project-diagram', + 'puzzle-piece', + 'qrcode', + 'question', + 'question-circle', + 'quidditch', + 'quote-left', + 'quote-right', + 'quran', + 'radiation', + 'radiation-alt', + 'rainbow', + 'random', + 'receipt', + 'record-vinyl', + 'recycle', + 'redo', + 'redo-alt', + 'registered', + 'remove-format', + 'reply', + 'reply-all', + 'republican', + 'restroom', + 'retweet', + 'ribbon', + 'ring', + 'road', + 'robot', + 'rocket', + 'route', + 'rss', + 'rss-square', + 'ruble-sign', + 'ruler', + 'ruler-combined', + 'ruler-horizontal', + 'ruler-vertical', + 'running', + 'rupee-sign', + 'sad-cry', + 'sad-tear', + 'satellite', + 'satellite-dish', + 'save', + 'school', + 'screwdriver', + 'scroll', + 'sd-card', + 'search', + 'search-dollar', + 'search-location', + 'search-minus', + 'search-plus', + 'seedling', + 'server', + 'shapes', + 'share', + 'share-alt', + 'share-alt-square', + 'share-square', + 'shekel-sign', + 'shield-alt', + 'ship', + 'shipping-fast', + 'shoe-prints', + 'shopping-bag', + 'shopping-basket', + 'shopping-cart', + 'shower', + 'shuttle-van', + 'sign', + 'sign-in-alt', + 'sign-language', + 'sign-out-alt', + 'signal', + 'signature', + 'sim-card', + 'sitemap', + 'skating', + 'skiing', + 'skiing-nordic', + 'skull', + 'skull-crossbones', + 'slash', + 'sleigh', + 'sliders-h', + 'smile', + 'smile-beam', + 'smile-wink', + 'smog', + 'smoking', + 'smoking-ban', + 'sms', + 'snowboarding', + 'snowflake', + 'snowman', + 'snowplow', + 'socks', + 'solar-panel', + 'sort', + 'sort-alpha-down', + 'sort-alpha-down-alt', + 'sort-alpha-up', + 'sort-alpha-up-alt', + 'sort-amount-down', + 'sort-amount-down-alt', + 'sort-amount-up', + 'sort-amount-up-alt', + 'sort-down', + 'sort-numeric-down', + 'sort-numeric-down-alt', + 'sort-numeric-up', + 'sort-numeric-up-alt', + 'sort-up', + 'spa', + 'space-shuttle', + 'spell-check', + 'spider', + 'spinner', + 'splotch', + 'spray-can', + 'square', + 'square-full', + 'square-root-alt', + 'stamp', + 'star', + 'star-and-crescent', + 'star-half', + 'star-half-alt', + 'star-of-david', + 'star-of-life', + 'step-backward', + 'step-forward', + 'stethoscope', + 'sticky-note', + 'stop', + 'stop-circle', + 'stopwatch', + 'store', + 'store-alt', + 'stream', + 'street-view', + 'strikethrough', + 'stroopwafel', + 'subscript', + 'subway', + 'suitcase', + 'suitcase-rolling', + 'sun', + 'superscript', + 'surprise', + 'swatchbook', + 'swimmer', + 'swimming-pool', + 'synagogue', + 'sync', + 'sync-alt', + 'syringe', + 'table', + 'table-tennis', + 'tablet', + 'tablet-alt', + 'tablets', + 'tachometer-alt', + 'tag', + 'tags', + 'tape', + 'tasks', + 'taxi', + 'teeth', + 'teeth-open', + 'temperature-high', + 'temperature-low', + 'tenge', + 'terminal', + 'text-height', + 'text-width', + 'th', + 'th-large', + 'th-list', + 'theater-masks', + 'thermometer', + 'thermometer-empty', + 'thermometer-full', + 'thermometer-half', + 'thermometer-quarter', + 'thermometer-three-quarters', + 'thumbs-down', + 'thumbs-up', + 'thumbtack', + 'ticket-alt', + 'times', + 'times-circle', + 'tint', + 'tint-slash', + 'tired', + 'toggle-off', + 'toggle-on', + 'toilet', + 'toilet-paper', + 'toolbox', + 'tools', + 'tooth', + 'torah', + 'torii-gate', + 'tractor', + 'trademark', + 'traffic-light', + 'trailer', + 'train', + 'tram', + 'transgender', + 'transgender-alt', + 'trash', + 'trash-alt', + 'trash-restore', + 'trash-restore-alt', + 'tree', + 'trophy', + 'truck', + 'truck-loading', + 'truck-monster', + 'truck-moving', + 'truck-pickup', + 'tshirt', + 'tty', + 'tv', + 'umbrella', + 'umbrella-beach', + 'underline', + 'undo', + 'undo-alt', + 'universal-access', + 'university', + 'unlink', + 'unlock', + 'unlock-alt', + 'upload', + 'user', + 'user-alt', + 'user-alt-slash', + 'user-astronaut', + 'user-check', + 'user-circle', + 'user-clock', + 'user-cog', + 'user-edit', + 'user-friends', + 'user-graduate', + 'user-injured', + 'user-lock', + 'user-md', + 'user-minus', + 'user-ninja', + 'user-nurse', + 'user-plus', + 'user-secret', + 'user-shield', + 'user-slash', + 'user-tag', + 'user-tie', + 'user-times', + 'users', + 'users-cog', + 'utensil-spoon', + 'utensils', + 'vector-square', + 'venus', + 'venus-double', + 'venus-mars', + 'vial', + 'vials', + 'video', + 'video-slash', + 'vihara', + 'voicemail', + 'volleyball-ball', + 'volume-down', + 'volume-mute', + 'volume-off', + 'volume-up', + 'vote-yea', + 'vr-cardboard', + 'walking', + 'wallet', + 'warehouse', + 'water', + 'wave-square', + 'weight', + 'weight-hanging', + 'wheelchair', + 'wifi', + 'wind', + 'window-close', + 'window-maximize', + 'window-minimize', + 'window-restore', + 'wine-bottle', + 'wine-glass', + 'wine-glass-alt', + 'won-sign', + 'wrench', + 'x-ray', + 'yen-sign', + 'yin-yang', ]; + + $tbicons = []; + foreach ($icons as $value) { + $tbicons[$value] = 'fas fa-'.$value; + } + + // Liste d'exemples d'icônes Font Awesome + return $tbicons; + } +} diff --git a/src/Form/Type/ThreeDigitType.php b/src/Form/Type/ThreeDigitType.php new file mode 100644 index 0000000..d04c230 --- /dev/null +++ b/src/Form/Type/ThreeDigitType.php @@ -0,0 +1,33 @@ +transformer = $transformer; + } + + public function buildForm(FormBuilderInterface $builder, array $options): void + { + $builder->addModelTransformer($this->transformer); + } + + public function configureOptions(OptionsResolver $resolver): void + { + } + + public function getParent(): string + { + return TextType::class; + } +} diff --git a/src/Form/UserType.php b/src/Form/UserType.php index 6dd1381..c005584 100644 --- a/src/Form/UserType.php +++ b/src/Form/UserType.php @@ -8,6 +8,7 @@ use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\EmailType; +use Symfony\Component\Form\Extension\Core\Type\HiddenType; use Symfony\Component\Form\Extension\Core\Type\PasswordType; use Symfony\Component\Form\Extension\Core\Type\RepeatedType; use Symfony\Component\Form\Extension\Core\Type\SubmitType; @@ -20,43 +21,45 @@ class UserType extends AbstractType public function buildForm(FormBuilderInterface $builder, array $options): void { $builder - ->add('submit', SubmitType::class, [ - 'label' => 'Valider', - 'attr' => ['class' => 'btn btn-success no-print'], - ]) + ->add('submit', SubmitType::class, [ + 'label' => 'Valider', + 'attr' => ['class' => 'btn btn-success no-print'], + ]) - ->add('username', TextType::class, [ - 'label' => 'Login', - ]) + ->add('username', TextType::class, [ + 'label' => 'Login', + ]) + ->add('password', RepeatedType::class, [ + 'type' => PasswordType::class, + 'required' => ('submit' == $options['mode'] ? true : false), + 'options' => ['always_empty' => true], + 'first_options' => ['label' => 'Mot de Passe', 'attr' => ['class' => 'form-control', 'style' => 'margin-bottom:15px', 'autocomplete' => 'new-password']], + 'second_options' => ['label' => 'Confirmer Mot de Passe', 'attr' => ['class' => 'form-control', 'style' => 'margin-bottom:15px']], + ]) + + ->add('avatar', HiddenType::class) + + ->add('email', EmailType::class, [ + 'label' => 'Email', + ]); + + if ('profil' != $options['mode']) { + $builder ->add('roles', ChoiceType::class, [ 'choices' => ['ROLE_ADMIN' => 'ROLE_ADMIN', 'ROLE_USER' => 'ROLE_USER'], 'multiple' => true, 'expanded' => true, ]) - ->add('password', RepeatedType::class, [ - 'type' => PasswordType::class, - 'required' => ('submit' == $options['mode'] ? true : false), - 'options' => ['always_empty' => true], - 'first_options' => ['label' => 'Mot de Passe', 'attr' => ['class' => 'form-control', 'style' => 'margin-bottom:15px', 'autocomplete' => 'new-password']], - 'second_options' => ['label' => 'Confirmer Mot de Passe', 'attr' => ['class' => 'form-control', 'style' => 'margin-bottom:15px']], - ]) - - ->add('avatar') - - ->add('email', EmailType::class, [ - 'label' => 'Email', - ]) - ->add('companys', EntityType::class, [ - 'label' => 'Companie', + 'label' => 'Compagnies', 'class' => Company::class, 'choice_label' => 'title', 'multiple' => true, 'attr' => ['class' => 'select2'], - ]) - ; + ]); + } } public function configureOptions(OptionsResolver $resolver): void diff --git a/src/Service/ImageService.php b/src/Service/ImageService.php new file mode 100644 index 0000000..21b5abe --- /dev/null +++ b/src/Service/ImageService.php @@ -0,0 +1,133 @@ + $maxWidth) { + $scale = $maxWidth / $width; + } + + // Création de l'image redimentionnée + $newImageWidth = ceil($width * $scale); + $newImageHeight = ceil($height * $scale); + $newImage = imagecreatetruecolor($newImageWidth, $newImageHeight); + + switch ($imageType) { + case 'image/gif': + $source = imagecreatefromgif($image); + break; + case 'image/pjpeg': + case 'image/jpeg': + case 'image/jpg': + $source = imagecreatefromjpeg($image); + break; + case 'image/png': + case 'image/x-png': + $source = imagecreatefrompng($image); + break; + case 'image/webp': + $source = imagecreatefromwebp($image); + break; + } + + imagecopyresampled($newImage, $source, 0, 0, 0, 0, $newImageWidth, $newImageHeight, $width, $height); + + switch ($imageType) { + case 'image/gif': + imagegif($newImage, $image); + break; + case 'image/pjpeg': + case 'image/jpeg': + case 'image/jpg': + imagejpeg($newImage, $image, 90); + break; + case 'image/png': + case 'image/x-png': + imagepng($newImage, $image); + break; + case 'image/webp': + imagewebp($newImage, $image, 90); + } + } + + public function cropImage(string $image, string $thumb, int $x, int $y, int $cropWidth, int $cropHeight, int $maxWidth, int $maxHeight): void + { + list($width, $height, $imageType) = getimagesize($image); + $imageType = image_type_to_mime_type($imageType); + + // Définir le pourcentage de réduction de l'image + $scale = $maxHeight / $cropHeight; + if (($cropWidth * $scale) > $maxWidth) { + $scale = $maxWidth / $cropWidth; + } + + // Création de l'image redimentionnée + $newImageWidth = ceil($cropWidth * $scale); + $newImageHeight = ceil($cropHeight * $scale); + + $newImage = imagecreatetruecolor($newImageWidth, $newImageHeight); + + switch ($imageType) { + case 'image/gif': + $source = imagecreatefromgif($image); + break; + case 'image/pjpeg': + case 'image/jpeg': + case 'image/jpg': + $source = imagecreatefromjpeg($image); + break; + case 'image/png': + case 'image/x-png': + $source = imagecreatefrompng($image); + break; + case 'image/webp': + $source = imagecreatefromwebp($image); + break; + } + + imagecopyresampled($newImage, $source, 0, 0, $x, $y, $newImageWidth, $newImageHeight, $cropWidth, $cropHeight); + + switch ($imageType) { + case 'image/gif': + imagegif($newImage, $thumb); + break; + case 'image/pjpeg': + case 'image/jpeg': + case 'image/jpg': + imagejpeg($newImage, $thumb, 90); + break; + case 'image/png': + case 'image/x-png': + imagepng($newImage, $thumb); + break; + case 'image/webp': + imagewebp($newImage, $thumb, 90); + } + } +} diff --git a/templates/accounting/edit.html.twig b/templates/accounting/edit.html.twig new file mode 100644 index 0000000..ec83f8c --- /dev/null +++ b/templates/accounting/edit.html.twig @@ -0,0 +1,40 @@ +{% extends 'base.html.twig' %} + +{% block title %} = {{title}}{% endblock %} + +{% block body %} +

{{title}}

+ + + {{ form_start(form) }} + {{ form_widget(form.submit) }} + Annuler + {%if mode=="update" %}Supprimer{%endif%} + + {% include('include/error.html.twig') %} + +
+
+
+
Information
+
+ {{ form_row(form.num01) }} + {{ form_row(form.num02) }} + {{ form_row(form.title) }} + {{ form_row(form.category) }} + {{ form_row(form.icon) }} +
+
+
+
+ {{ form_end(form) }} + +{% endblock %} + +{% block localscript %} + +{% endblock %} diff --git a/templates/accounting/list.html.twig b/templates/accounting/list.html.twig new file mode 100644 index 0000000..88b67d9 --- /dev/null +++ b/templates/accounting/list.html.twig @@ -0,0 +1,49 @@ +{% extends 'base.html.twig' %} + +{% block title %} = {{title}}{% endblock %} + +{% block body %} +

{{title}}

+ Ajouter + +
+ + + + + + + + + + + + {% for accounting in accountings %} + + + + + + + {% endfor %} + +
ActionIcôneCompteCatégorieTitre
+ {% if accounting.icon %} + + {% endif %} + {{accounting.num01}}-{{accounting.num02}}{{accounting.category}}{{accounting.title}}
+
+{% endblock %} + +{% block localscript %} + +{% endblock %} diff --git a/templates/base.html.twig b/templates/base.html.twig index 6b138af..48df598 100644 --- a/templates/base.html.twig +++ b/templates/base.html.twig @@ -13,6 +13,8 @@ + + @@ -23,6 +25,7 @@ + {% block javascripts %} @@ -42,9 +45,7 @@ + {% endif %} diff --git a/templates/security/login.html.twig b/templates/security/login.html.twig index fd622db..8c226b6 100644 --- a/templates/security/login.html.twig +++ b/templates/security/login.html.twig @@ -35,12 +35,9 @@ {% endblock %} {% block localscript %} - {% endblock %} diff --git a/templates/crop/crop01.html.twig b/templates/upload/crop01.html.twig similarity index 79% rename from templates/crop/crop01.html.twig rename to templates/upload/crop01.html.twig index 4aec7eb..258b1e4 100644 --- a/templates/crop/crop01.html.twig +++ b/templates/upload/crop01.html.twig @@ -10,20 +10,23 @@ {% block body %} Annuler -
{% endblock %} - - {% block localscript %} +{% endblock %} diff --git a/templates/user/edit.html.twig b/templates/user/edit.html.twig index 6a7170a..ffcc021 100644 --- a/templates/user/edit.html.twig +++ b/templates/user/edit.html.twig @@ -9,13 +9,18 @@ {{ form_start(form) }} {{ form_widget(form.submit) }} Annuler - {%if mode!="submit" %}Supprimer{%endif%} + {%if mode=="update" %}Supprimer{%endif%} + {% include('include/error.html.twig') %} - Modifier +
+ + {{ form_row(form.avatar) }} + Modifier +
-
+
Information
@@ -26,22 +31,24 @@
-
-
-
Permissions
-
- {{ form_row(form.roles) }} - {{ form_row(form.companys) }} + {%if form.roles is defined%} +
+
+
Permissions
+
+ {{ form_row(form.roles) }} + {{ form_row(form.companys) }} +
-
+ {%endif%}
{{ form_end(form) }} {% endblock %} {% block localscript %} -