Compare commits

...

227 Commits

Author SHA1 Message Date
llaniau cf057c9c63 V2.0.1 2020-06-29 17:15:02 +02:00
llaniau e5c46b2985 Mise en place bootstrap V2.0.1 2020-06-29 15:44:07 +02:00
Sébastien 47d571baae Fix : Button disabled 2020-02-12 09:26:05 +01:00
Sébastien f5f0c39dd7 Feat : Update style of answer page 2020-02-04 08:15:33 +01:00
Grégoire c83b71853b feat and fix : statut of answer last message / add no empty message / delete statut CHAT 2020-01-14 16:05:31 +01:00
Grégoire 8bc3165995 fix : ajaxRecStat on user null for google robot (3) 2020-01-03 11:13:20 +01:00
Grégoire dffcf66ce3 fix : ajaxRecStat on user null for google robot (2) 2020-01-03 11:09:31 +01:00
Grégoire 41c046392e fix : ajaxRecStat on user null for google robot 2020-01-03 10:59:25 +01:00
Grégoire e81e2dce9d fix : problem saving company user parameters
hide birthday field (date issue) /entreprise/me/mon_compte
2020-01-03 10:25:26 +01:00
Grégoire 3ffc3c8d3b fix : sendtime + message video + contact_talent 2020-01-02 15:29:55 +01:00
Grégoire e35cb0c461 fix : link mail answer spontaneous 2019-12-30 16:22:13 +01:00
Grégoire db084707bb fix : search bar v2 2019-12-30 13:20:11 +01:00
Grégoire 1a9fff778a fix : search bar 2019-12-30 12:27:11 +01:00
Sébastien 90a38edb29 Fix: Add new noreply email 2019-11-28 08:31:58 +01:00
Sébastien fc1b4a3e2a Feat: add popup when change company user email 2019-11-26 08:52:59 +01:00
Sebastien Glatz 94a946e36d Fix: little space fix 2019-11-22 16:12:09 +01:00
Sébastien f06cbe296f Fix: Banner color and padding 2019-11-21 15:56:48 +01:00
Sébastien e2a98aaed3 Feat: Edit form to add bootstrap style on input 2019-11-21 15:36:32 +01:00
Sébastien beee2c5635 Feat: Add field email on Company Edition 2019-11-21 14:33:42 +01:00
Grégoire bca29b9547 delete TalentController api 2019-11-05 14:07:50 +01:00
Grégoire 823a781d3a minor fix Push Notification 2019-11-05 11:24:34 +01:00
Grégoire 2a9e728354 correctif Menu 2019-10-28 17:03:46 +01:00
Grégoire 074c125f8c Redirect monCompte API 2019-10-28 14:36:14 +01:00
Grégoire 0b2898d170 Add twitter, linkedin … for getIdCard() 2019-10-15 09:57:37 +02:00
Grégoire 12525dbf16 Merge branch 'master' of https://git.e-declic.net/talents-tube/website 2019-10-14 16:43:13 +02:00
Grégoire 4a17adf687 add phone / linkedin / twitter … field for API form 2019-10-14 16:32:39 +02:00
Huaoe f4e412d792 Merge branch 'master' of https://git.e-declic.net/talents-tube/website 2019-10-11 15:48:44 +02:00
Grégoire 61786797c8 API : add getUserSubscriptionToPush (old : isUserSubscribedToPush) 2019-10-11 15:17:43 +02:00
Huaoe 57587a4a97 Merge branch 'master' of https://git.e-declic.net/talents-tube/website 2019-10-11 14:29:20 +02:00
Grégoire fd048d5a0e Merge branch 'master' of https://git.e-declic.net/talents-tube/website 2019-10-11 14:19:28 +02:00
Grégoire 229893dc95 API : add isUserSubscribedToPush 2019-10-11 14:19:02 +02:00
Grégoire 26c6e2103d API : ad visit record for companies and ads pages 2019-10-10 16:59:08 +02:00
Grégoire 8830b5ccde Set isPrivate true by default for companies 2019-10-10 16:57:50 +02:00
Huaoe 2bc2d87b8c UpdateUser fix request->request 2019-10-10 16:24:23 +02:00
Huaoe 278c558c9e Merge branch 'master' of https://git.e-declic.net/talents-tube/website 2019-10-10 14:49:02 +02:00
Huaoe 98545707b3 photo return 2019-10-09 17:01:58 +02:00
Sébastien 52d105efb4 Feat: add field phone and edit set extra 2019-10-09 11:31:53 +02:00
Sébastien 027c3fd2d1 Fix: presentationVideo syntax error 2019-10-09 11:27:52 +02:00
Grégoire 824ff9f1ec Change query / no selecting talent video in chat 2019-10-09 10:48:56 +02:00
Grégoire 606e29280b Fix bug draft message show app 2019-10-08 16:05:19 +02:00
Sébastien 3a29c647dd Fix: serialize tags for answer 2019-10-07 15:15:18 +02:00
Huaoe 57dd053693 Merge branch 'master' of https://git.e-declic.net/talents-tube/website 2019-10-07 09:51:42 +02:00
Huaoe e57173f835 upload profil picture 2019-10-07 09:51:35 +02:00
Sébastien 8f4ef35ddf Feat: Serialize publicTag for offer detail 2019-10-04 13:48:37 +02:00
Sébastien 346b788f83 Feat: Add titleTalent in extra to update from app 2019-10-04 13:48:08 +02:00
Sébastien edf35c74e8 Feat: Serialize territory type 2019-10-01 18:11:08 +02:00
Sébastien 75f2bbf6a7 Fix: php syntax error 2019-10-01 18:10:15 +02:00
Grégoire 0cbe670c90 change order for entreprises 2019-10-01 16:28:52 +02:00
Sébastien 2d595c1c3a Serialize territories for ad detail 2019-09-26 11:41:08 +02:00
Sébastien 98ebde7e72 Add linkedin twitter and website data for app 2019-09-26 11:40:36 +02:00
Huaoe d607962523 style.css generated 2019-09-16 16:20:09 +02:00
Huaoe b4ae35f4a6 yellow banner Off 2019-09-16 16:18:44 +02:00
Huaoe be37e97a19 fix PWA link 2019-09-16 15:50:53 +02:00
Huaoe d21febaaa1 css update 2019-09-16 14:54:03 +02:00
Huaoe 6acba9c082 css + tag manager 2019-09-16 14:43:38 +02:00
Huaoe 65147a9ac6 dev BDDD paswword 2019-09-13 14:00:00 +02:00
Huaoe a366ed749e merge Ad repo 2019-09-12 12:02:22 +02:00
Huaoe 87f6956958 isPrivate 2019-09-12 12:00:27 +02:00
Huaoe 3a78ac68f2 isPrivate in search ad 2019-09-11 16:21:11 +02:00
Sébastien 39774c1ed9 Merge branch 'master' of https://git.e-declic.net/talents-tube/website 2019-09-10 15:40:15 +02:00
Sébastien bd477b3354 Fix: ads order list 2019-09-10 15:38:13 +02:00
Sébastien 86e33a5e0a Fix: mysql-client to mariadb-client 2019-09-10 08:45:20 +02:00
Huaoe 365c71751d assetic fix 2019-09-09 17:27:40 +02:00
Huaoe 46399bd8ed typo notifications 2019-09-09 15:07:52 +02:00
Huaoe c3a8fa73cd Makefile CLIENT name 2019-09-09 14:08:36 +02:00
Huaoe fe7c9992a5 Makefile + Security spaces removal 2019-09-09 10:40:03 +02:00
Huaoe 1922ab328b uncomment video de la home 2019-09-09 09:24:53 +02:00
Huaoe a91f2df040 Update Docker SEb 2019-09-06 16:41:05 +02:00
Huaoe 1a4e81963e delete css 2019-09-04 15:47:19 +02:00
Huaoe 5ae61ff2c7 sass gen
don't know if delete would be good
2019-09-04 15:44:25 +02:00
Huaoe 995bb0b43e Merge branch 'feat/push'
# Conflicts:
#	volume/www/website/www/app/config/fos_elastica.yml
#	volume/www/website/www/src/AppBundle/Entity/User.php
#	volume/www/website/www/web/assetic/main.dash.talent.js
#	volume/www/website/www/web/css/styles.css
2019-09-04 15:42:48 +02:00
Huaoe 4c841aaafa use Authentication\Token\UsernamePasswordToken 2019-09-02 17:15:29 +02:00
Huaoe 49abf8d86f purge elastica + db user pass 2019-09-02 14:28:32 +02:00
Huaoe e3ca74f09b sass execution 2019-09-02 14:08:06 +02:00
Huaoe 6818e82c92 style sass transform stalling 2019-09-02 14:07:47 +02:00
Huaoe 2ea95f529e config fos elastica +backup 2019-09-02 11:11:55 +02:00
Huaoe 6cec286886 Merge branch 'push'
# Conflicts:
#	volume/www/website/www/app/config/fos_elastica.yml
#	volume/www/website/www/src/AppBundle/Entity/User.php
#	volume/www/website/www/vendor/bin/doctrine
#	volume/www/website/www/vendor/bin/doctrine-dbal
#	volume/www/website/www/vendor/bin/security-checker
#	volume/www/website/www/vendor/bin/simple-phpunit
#	volume/www/website/www/web/assetic/main.dash.talent.js
#	volume/www/website/www/web/css/styles.css
2019-09-02 11:11:05 +02:00
Huaoe f38d22d70d delete vendors 2019-09-02 10:37:49 +02:00
Huaoe b5791997d8 Merge remote-tracking branch 'origin/master' into feat/push
# Conflicts:
#	volume/www/website/www/app/config/fos_elastica.yml
#	volume/www/website/www/src/AppBundle/Entity/User.php
#	volume/www/website/www/web/assetic/main.dash.talent.js
#	volume/www/website/www/web/css/styles.css
2019-09-02 10:30:32 +02:00
Huaoe d51add8f1d comment yellow bar 2019-09-02 09:31:47 +02:00
Huaoe 579c800dc9 📲 2019-08-29 16:01:46 +02:00
Huaoe 24897eab5e space 2019-08-29 15:59:52 +02:00
Sébastien GLATZ bde2c84cde Add banner for new app 2019-08-29 15:56:04 +02:00
Huaoe eee791b08f address in add company 2019-08-27 16:52:35 +02:00
Huaoe 874027d494 chat messages api done 2019-08-26 15:16:46 +02:00
Thomas Berrod 328a3821b8 message 2019-08-21 17:30:54 +02:00
Thomas Berrod 807a9351ea facebook stalling 2019-08-19 17:19:33 +02:00
Thomas Berrod 21f5912384 wkf Answer + reset password 2019-08-12 15:45:29 +02:00
Thomas Berrod 2d35cd41f1 formating 2019-08-09 15:14:52 +02:00
Thomas Berrod 04a3a0d9c7 bug fix :undefined varible 2019-08-09 15:14:13 +02:00
Thomas Berrod be7e738839 test join company 2019-08-09 14:53:32 +02:00
Thomas Berrod 67825d024d Company join on ads 2019-08-09 11:50:47 +02:00
Thomas Berrod 85ba5dcbae thomas email change 2019-08-09 09:47:42 +02:00
Thomas Berrod b914b0ea96 answer directly to status SENDED 2019-08-08 15:43:14 +02:00
Thomas Berrod 48240d5cab fix : candidature spontanée even if answered to ad 2019-08-08 15:38:05 +02:00
Thomas Berrod c1dc54d036 comment out 2019-08-07 17:09:44 +02:00
Thomas Berrod c801856bfc filtre company 2019-08-07 17:05:01 +02:00
Thomas Berrod e8c9052e35 exposing businessname on ad_detail 2019-08-06 11:18:04 +02:00
Thomas Berrod b86aa8960b bug fix on POST answer 2019-08-05 17:00:37 +02:00
Thomas Berrod c770fd16c2 $token missing 2019-08-01 17:18:31 +02:00
gregoire 36fa91f2b3 Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-08-01 14:53:11 +02:00
gregoire ff55b409e0 variable verification + security 2019-08-01 14:53:05 +02:00
Thomas Berrod ee57f4ebaf fix echo in login facebook flow 2019-07-31 15:02:07 +02:00
Thomas Berrod cd3b2986a5 fix facebook email issue 2019-07-31 14:56:50 +02:00
Thomas Berrod 79a075a034 facebook use accesstoken for profile fetch 2019-07-31 14:37:22 +02:00
Thomas Berrod ad8581d9e7 facebook get profil PROD access code 2019-07-31 11:11:38 +02:00
Thomas Berrod 371493e01f Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-07-30 17:12:58 +02:00
Thomas Berrod 64210c330b hard change facebook access_token 2019-07-30 17:12:54 +02:00
Thomas Berrod 088f7f2edc creation time added to JSON answers... 2019-07-30 17:12:12 +02:00
Thomas Berrod d01afc28aa bug fix offre pourvues 2019-07-30 15:27:39 +02:00
gregoire d831ffaff5 Only one answer by user / offer implementation 2019-07-30 10:15:34 +02:00
gregoire f540542aa0 Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-07-26 10:22:00 +02:00
Thomas Berrod dd9d6f7901 Answers fixes 2019-07-25 14:56:06 +02:00
gregoire 714bd5ff87 debut Exception 2019-07-25 09:15:55 +02:00
gregoire 9cb079cbba question readme + spontaneous answer 2019-07-23 17:29:01 +02:00
gregoire 8003feec05 Post answer 2019-07-23 16:34:17 +02:00
gregoire 4616dbd65a add type annotation 2019-07-23 12:08:29 +02:00
Thomas Berrod 1ef4a57848 Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-07-22 17:36:40 +02:00
Thomas Berrod 8bae304f0d beginnings on post answers 2019-07-22 17:36:27 +02:00
gregoire acacaae6de readme notification + public key 2019-07-22 17:29:44 +02:00
Thomas Berrod fb8239e987 groups on company / ads 2019-07-22 11:38:42 +02:00
gregoire 088e680230 change keys for push notification 2019-07-22 10:01:43 +02:00
Thomas Berrod 2fdc095c31 "company_detail" added 2019-07-19 16:53:55 +02:00
Thomas Berrod 4ca1962829 zzz off 2019-07-19 16:49:35 +02:00
Thomas Berrod 19e3b11066 Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-07-19 16:49:04 +02:00
Thomas Berrod ef2550568f Revert "Add group serializer"
This reverts commit b50ad1de77.
2019-07-19 16:48:40 +02:00
gregoire 9845e11954 fuck 2019-07-19 16:48:40 +02:00
gregoire 0447b333ec fix problem website + test 2019-07-19 16:48:40 +02:00
Thomas Berrod fb58eaec0f company search fix 2019-07-19 16:48:40 +02:00
gregoire b145eb1628 fix company for user 2019-07-19 16:48:40 +02:00
Sébastien GLATZ d29cb07d46 Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-07-19 16:33:23 +02:00
Sébastien GLATZ b50ad1de77 Add group serializer 2019-07-19 16:33:12 +02:00
gregoire 4cad444833 fuck 2019-07-19 16:13:20 +02:00
gregoire 94885d96bc fix problem website + test 2019-07-19 14:54:39 +02:00
gregoire 6902b005b4 Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-07-19 14:17:47 +02:00
gregoire 2b9abe5bec fix company for user 2019-07-19 14:16:46 +02:00
Thomas Berrod 8fa429e35a Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-07-19 14:09:32 +02:00
Sébastien GLATZ 81eb21d84b Add group serializer 2019-07-19 11:45:01 +02:00
Thomas Berrod 097dd88b5e company search fix 2019-07-19 09:21:13 +02:00
gregoire 527ab850db regex for requirements companycontroller 2019-07-18 11:04:27 +02:00
gregoire fbc2e414ea securit.yml correction + add extra serialize group 2019-07-18 09:57:07 +02:00
gregoire c81b5e9c51 Add comment in serialize answer + path security 2019-07-18 09:30:32 +02:00
gregoire 57e5c2eff6 Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-07-17 17:12:58 +02:00
gregoire 6e29500a1b ORM pdf schema + serialize candidature 2019-07-17 17:12:53 +02:00
Sébastien GLATZ 23423cd831 Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-07-17 14:41:43 +02:00
Sébastien GLATZ 3e2827d624 Add group serializer 2019-07-17 14:41:35 +02:00
Thomas Berrod 08bb1ea10e bug fix : search company on brandName 2019-07-17 12:09:14 +02:00
Thomas Berrod f1e23410d4 bug fix : to lower search 2019-07-17 11:13:52 +02:00
Thomas Berrod 922f526ddd bug fix : consecutive where setparrameter distinct id 2019-07-17 11:12:28 +02:00
Thomas Berrod 9a4de2f6ca company emphasis 2019-07-17 10:13:10 +02:00
gregoire a4995ac616 Reset Password API 2019-07-17 10:08:49 +02:00
Sébastien GLATZ 8f70911b2e Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-07-17 08:37:08 +02:00
Sébastien GLATZ 54c255cf33 Add group serializer to is_promoted (pourvue) 2019-07-17 08:37:00 +02:00
gregoire 553727cbe1 Add UpdateUser function for API 2019-07-16 15:49:35 +02:00
gregoire 783485b96e merge emphasis 2019-07-16 11:33:15 +02:00
gregoire f01215b074 countAds implementation 2019-07-16 11:25:29 +02:00
Thomas Berrod e65afe3b24 emphasis 2019-07-16 11:18:50 +02:00
Thomas Berrod c3696934e9 push params prod config 2019-07-16 09:20:06 +02:00
Thomas Berrod 12cc628f14 preprod conf 2019-07-11 11:07:21 +02:00
Thomas Berrod c63302acbf Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-07-11 10:27:18 +02:00
Sébastien GLATZ 6aa736a4a2 Update serialized field 2019-07-11 10:23:56 +02:00
Sébastien GLATZ 05ceeb440e Add countAds 2019-07-11 10:23:56 +02:00
Sébastien GLATZ 539878e73b Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push 2019-07-09 09:26:29 +02:00
Thomas Berrod 1c7a1732a6 slug service fix 2019-07-08 18:37:50 +02:00
Thomas Berrod ac975c7604 fix findUserWithFacebookEmailAndAttach 2019-07-08 18:26:27 +02:00
Thomas Berrod 56d2f199b5 remove dumps 2019-07-08 18:22:17 +02:00
Thomas Berrod 1a3955a605 composer update 2019-07-08 14:50:37 +02:00
Sébastien GLATZ e69b5d80cd Update API data 2019-07-08 10:02:14 +02:00
Thomas Berrod 8706d63867 api register + twig loginbutton logical fix 2019-07-05 15:26:11 +02:00
Thomas Berrod 8c0c1f7720 return $data->elements[0]->{'handle~'}->emailAdress; 2019-07-04 17:41:12 +02:00
Thomas Berrod 2628883568 typo 2019-07-04 17:33:29 +02:00
Thomas Berrod 8918b3708b linkedin double request for email 2019-07-04 17:19:58 +02:00
Thomas Berrod f75989129e docker file + facebook photo 2019-07-03 17:11:27 +02:00
Thomas Berrod 0b563e9658 security config + fetch user 2019-06-21 16:28:03 +02:00
Thomas Berrod 9e70ee745b removed proxy generation during dev 2019-06-20 17:24:58 +02:00
Thomas Berrod 3bdc496c03 company groups stable 2019-06-20 12:12:46 +02:00
Thomas Berrod 1cccee38b8 Rest auth facebook linkedin Beta 2019-06-17 17:36:09 +02:00
Thomas MONCHICOURT e613fa78fb #9766 texte 2019-06-14 11:42:38 +02:00
Thomas MONCHICOURT a552221f60 #9792 déactivation linkedIn 2019-06-14 11:34:33 +02:00
Thomas MONCHICOURT 0b7db51bfb Feat #9689 texttrack=fr forcé 2019-06-05 16:08:21 +02:00
Thomas Berrod a97a794dec media upload config 2019-06-05 11:59:24 +02:00
Sébastien GLATZ 1c2a944ca5 Merge branch 'feat/push' of https://git.e-declic.net/talents-tube/website into feat/push
# Conflicts:
#	conf/build/php/Dockerfile
2019-05-29 14:31:13 +02:00
Sébastien GLATZ 08555463fd Ajout groupes de sérialization 2019-05-29 14:24:03 +02:00
Thomas Berrod a8c04f48b0 #9658 first upload Answer controller 2019-05-23 15:04:47 +02:00
Thomas Berrod 0c86cd00ac #9658 : first media upload 2019-05-23 15:04:17 +02:00
Sébastien GLATZ 60365023ac Feat : Ajout groupe sérialisation pour API 2019-05-22 10:06:24 +02:00
Sébastien GLATZ 2c40323718 Fix : Modification configurations base + libpng-dev 2019-05-22 09:57:30 +02:00
Thomas Berrod 76a028cd88 Fix: typo + company search 2019-05-17 15:38:59 +02:00
Thomas Berrod 52ad0cf32e Fix : typo 2019-05-16 15:19:51 +02:00
Thomas Berrod 7e94b1e104 delete makefile backup 2019-05-16 10:18:14 +02:00
Thomas Berrod 54e971d918 make file windows compat 2019-05-16 10:17:43 +02:00
Thomas Berrod 3a82158fe3 deletes 2019-05-16 10:14:05 +02:00
Thomas Berrod 34b3e260bc Merge branch 'feat/api-rest' into feat/push
# Conflicts:
#	Makefile
2019-05-16 10:13:28 +02:00
Thomas Berrod 362006818e makefile 2019-05-16 09:58:18 +02:00
Thomas Berrod d6f8941e47 unknown deletes 2019-05-16 09:46:59 +02:00
Thomas Berrod 0d0c725aaf dernier travaux sur notif : voir les todos 2019-02-05 12:07:41 +01:00
Thomas Berrod a5742f2c1e typo sur offstet 2018-09-24 16:33:55 +02:00
Thomas Berrod 57b7db7f43 styling notification toast 2018-09-20 11:51:17 +02:00
Thomas Berrod db07bc80c8 analytics plug on push 2018-09-19 13:57:12 +02:00
Thomas Berrod 1e03451b37 notification param in talent/me + delayed trigger on 3 times entreprise viewed 2018-09-18 16:48:56 +02:00
Maxime Thévenot b1185018de Feat : composer update after merge 2018-09-17 12:30:04 +02:00
Maxime Thévenot 5d8357231c Conf : add gmp to php container 2018-09-17 12:29:42 +02:00
Thomas Berrod 5474397f5f Merge branch 'feat/api-rest' of https://git.e-declic.net/talents-tube/website into feat/api-rest 2018-09-17 10:49:18 +02:00
Maxime Thévenot aeb4328e23 Merge branch 'feat/api-rest' into feat/push
# Conflicts:
#	volume/www/website/www/app/AppKernel.php
#	volume/www/website/www/app/config/config.yml
#	volume/www/website/www/app/config/parameters-dev.yml
#	volume/www/website/www/app/config/parameters.yml.dist
#	volume/www/website/www/app/config/routing.yml
#	volume/www/website/www/app/config/services.yml
#	volume/www/website/www/composer.json
#	volume/www/website/www/composer.lock
#	volume/www/website/www/vendor/composer/autoload_files.php
#	volume/www/website/www/vendor/composer/autoload_psr4.php
#	volume/www/website/www/vendor/composer/autoload_static.php
#	volume/www/website/www/vendor/composer/installed.json
#	volume/www/website/www/vendor/ocramius/package-versions/src/PackageVersions/Versions.php
#	volume/www/website/www/web/css/styles.css
2018-09-17 10:29:41 +02:00
Maxime Thévenot 44d0711dc1 Feat : Add company and answer api base 2018-09-17 10:15:12 +02:00
Thomas Berrod 9f6c1a740f Merge branch 'feat/api-rest' of https://git.e-declic.net/talents-tube/website into feat/api-rest 2018-09-17 09:04:25 +02:00
Thomas Berrod 8063c8479e feat:adding quotes to makefile 2018-09-10 09:53:07 +02:00
Thomas Berrod 56444f6363 feat: update coriolis json 2018-09-10 09:04:00 +02:00
Maxime Thévenot 04229b0781 Feat : implement token generation with facebook id 2018-09-07 14:31:32 +02:00
Maxime Thévenot 4edfae9f1c Feat : implement JWT for api authentication 2018-09-07 08:57:44 +02:00
Maxime Thévenot 870654c850 Feat : update ads representation 2018-09-06 09:48:12 +02:00
Maxime Thévenot 9413202660 WIP : test authentication for api 2018-09-06 08:20:27 +02:00
Maxime Thévenot 215e325a8c Feat : configure and test api on add 2018-09-06 08:20:09 +02:00
Maxime Thévenot 9f8682c896 Feat : Install hateoas bundle 2018-09-06 08:19:16 +02:00
Thomas Berrod ff33129d80 merge windows makefile 2018-09-03 17:28:40 +02:00
Thomas Berrod 1b76548c91 Merge branch 'push_feature' of https://git.e-declic.net/talents-tube/website into push_feature 2018-09-03 17:18:52 +02:00
Thomas Berrod 9578eb96c9 profil & tags ùatching push 2018-09-03 17:14:46 +02:00
Thomas Berrod c4af665c26 general + email + profil completeness 2018-08-31 17:36:01 +02:00
Maxime Thévenot c48fe53e6a Feat : install pagerfante bundle and update api 2018-08-31 16:44:42 +02:00
Maxime Thévenot d69f32c657 Feat : update config.yml for fosrest and add some api method 2018-08-31 12:07:29 +02:00
Maxime Thévenot dba776d15f Update : symfony to 3.4 + vendors 2018-08-31 11:26:11 +02:00
Maxime Thévenot bb3ed610ab WIP : testing api 2018-08-31 10:40:47 +02:00
Maxime Thévenot 75145d9e1c Feat : install FOSRestBundle 2018-08-29 15:26:50 +02:00
Maxime Thévenot b885e6866c Feat : install jmsserializer bundle 2018-08-29 14:42:12 +02:00
Maxime Thévenot dbb06990d5 Conf: update uglify-js to uglify-es 2018-08-29 12:01:23 +02:00
Maxime Thévenot f8c0b75ec2 Conf : update docker config for windows compatbility 2018-08-29 11:56:57 +02:00
Thomas Berrod dca95338a9 push localhost only 2018-08-28 15:12:51 +02:00
16591 changed files with 717927 additions and 147457 deletions
+2
View File
@@ -10,3 +10,5 @@
volume/www/website/.idea
/volume/www/website/store/themes/talentstube-20170413/cache/*
/volume/www/website/store/img/tmp/*
volume/www/website/www/app/Resources/views/default/index.html.twig
TODO
+23 -7
View File
@@ -2,7 +2,7 @@
CLIENT=tt-website
DOCKERCOMPOSE := $(shell command -v docker-compose 2> /dev/null)
USAGE := Usage: make ENV={prod|preprod|dev} {docker-build|docker-start|docker-stop|docker-restart}
USAGE := Usage: make ENV={prod|preprod|dev} {SYS=windows|linux} {docker-build|docker-start|docker-stop|docker-restart}
ifndef DOCKERCOMPOSE
$(error docker-compose is not available)
@@ -14,16 +14,23 @@ $(info $(USAGE))
$(error Exiting)
endif
SYS=linux
DC_OVERRIDE := $(shell test -e conf/docker-compose.override.yml && echo "--file conf/docker-compose.override.yml")
DC_OVERRIDE_ENV := $(shell test -e conf/docker-compose.$(ENV).yml && echo "--file conf/docker-compose.$(ENV).yml")
DC=ENV=$(ENV) CLIENT=$(CLIENT) $(DOCKERCOMPOSE) --project-name "$(CLIENT)_$(ENV)" --file conf/docker-compose.yml $(DC_OVERRIDE) $(DC_OVERRIDE_ENV)
ifeq ($(SYS),linux)
DC=ENV=$(ENV) CLIENT=$(CLIENT) "$(DOCKERCOMPOSE)" --project-name "$(CLIENT)_$(ENV)" --file conf/docker-compose.yml $(DC_OVERRIDE) $(DC_OVERRIDE_ENV)
else
DC=ENV=$(ENV) CLIENT=$(CLIENT) "$(DOCKERCOMPOSE)" --project-name "$(CLIENT)_$(ENV)" --file conf/docker-compose.win.yml $(DC_OVERRIDE) $(DC_OVERRIDE_ENV)
endif
default:
$(info $(USAGE))
$(error Exiting)
docker-build:
$(DC) pull
$(DC) build
$(DC) up -d
@@ -57,8 +64,8 @@ config:
@echo " --> Generating mysql auth file"
@cat conf/env/store-mysql.env \
| python -c "import sys; import string; v=sys.stdin.readline().split('MYSQL_ROOT_PASSWORD=')[1]; print(string.Template(open('conf/build/mysql/my.cnf').read()).substitute({'PASSWORD':v}))" \
| docker exec -i $(CLIENT).store-mysql.$(ENV) sh -c 'cat > /root/.my.cnf'
| python -c "import sys; import string; v=sys.stdin.readline().split('MYSQL_ROOT_PASSWORD=')[1]; print(string.Template(open('conf/build/mysql/my.cnf').read()).substitute({'PASSWORD':v}))" \
| docker exec -i $(CLIENT).store-mysql.$(ENV) sh -c 'cat > /root/.my.cnf'
db-backup-all: db-backup-website db-backup-store
@@ -76,9 +83,14 @@ db-backup-store:
db-restore-all: db-restore-website db-restore-store
db-backup-script:
@mkdir -p backup/
@docker exec $(CLIENT).postgres.$(ENV) pg_dumpall --database database -c -U postgres > backup/postgres_$(ENV)_`date +%d-%m-%Y"_"%H_%M_%S`.sql
@docker exec $(CLIENT).store-mysql.$(ENV) mysqldump -uroot database > backup/store-mysql_$(ENV)_`date +%d-%m-%Y"_"%H_%M_%S`.sql
db-restore-website:
@echo "Restoring file to database (backup/store-mysql.sql)"
@cat backup/postgres.sql | docker exec -i $(CLIENT).postgres.$(ENV) psql --dbname database -U postgres
@echo "Restoring file to database (backup/postgres.sql)"
@cat backup/postgres.sql | docker exec -i $(CLIENT).postgres.$(ENV) psql --dbname database -U user
@docker cp backup/mongo $(CLIENT).mongo.$(ENV):/
@docker exec -t $(CLIENT).mongo.$(ENV) mongorestore --drop --gzip --db=tt_history /mongo/tt_history
@@ -95,7 +107,7 @@ entities:
@docker exec -i $(CLIENT).php.$(ENV) su www-data --shell=/bin/bash -c "/home/www/website/www/bin/console doctrine:generate:entities AppBundle"
db-diff:
@docker exec -i $(CLIENT).php.$(ENV) su www-data --shell=/bin/bash -c "/home/www/website/www/bin/console doctrine:migrations:diff"
@docker exec -i $(CLIENT).php.$(ENV) su www-data -c "/home/www/website/www/bin/console doctrine:migrations:diff"
db-migrate:
@docker exec -i $(CLIENT).php.$(ENV) su www-data --shell=/bin/bash -c "/home/www/website/www/bin/console doctrine:migrations:migrate"
@@ -104,3 +116,7 @@ db-deploy: db-diff db-migrate
es-populate:
@docker exec -i $(CLIENT).php.$(ENV) su www-data --shell=/bin/bash -c "/home/www/website/www/bin/console fos:elastica:populate"
sys:
@echo $(SYS)
@echo $(DC)
+3
View File
@@ -0,0 +1,3 @@
Todo:
☐ Item
+31 -24
View File
@@ -1,47 +1,54 @@
FROM php:7.1-fpm
FROM php:7.1-fpm-buster
ENV TERM=xterm
RUN echo 'deb http://ftp.debian.org/debian jessie-backports main' > /etc/apt/sources.list.d/debian-backports.list
#RUN printf "deb http://archive.debian.org/debian/ jessie main\ndeb-src http://archive.debian.org/debian/ jessie main\ndeb http://security.debian.org jessie/updates main\ndeb-src http://security.debian.org jessie/updates main\ndeb http://archive.debian.org/debian/ jessie-backports main" > /etc/apt/sources.list.d/debian-backports.list
RUN apt-get clean \
&& apt-get update \
&& apt-get install -y lsof nano less git locales
&& apt-get update \
&& apt-get install -y lsof nano less git locales
RUN echo 'fr_FR.UTF-8 UTF-8' > /etc/locale.gen \
&& /usr/sbin/locale-gen
&& /usr/sbin/locale-gen
RUN apt-get update \
&& apt-get install -y ffmpeg exiftool graphviz libfreetype6-dev libjpeg62-turbo-dev libpng12-dev libmcrypt-dev libxslt-dev libicu-dev libxml2-dev libpq-dev libgeoip-dev libedit-dev mysql-client nodejs npm \
&& apt-get install -y --no-install-recommends libmagickwand-dev \
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install -j4 gd mcrypt xsl zip intl gettext soap pdo_pgsql pdo_mysql mysqli pgsql json readline opcache \
&& pecl install geoip-1.1.1 redis imagick mongodb \
&& docker-php-ext-enable geoip redis imagick mongodb
&& apt-get -y install libgmp-dev \
&& ln -s /usr/include/x86_64-linux-gnu/gmp.h /usr/local/include/gmp.h \
&& docker-php-ext-install gmp \
&& docker-php-ext-configure gmp
RUN apt-get update \
&& apt-get install -y ffmpeg exiftool graphviz libfreetype6-dev libjpeg62-turbo-dev libpng-dev libmcrypt-dev libxslt-dev libicu-dev libxml2-dev libpq-dev libgeoip-dev libedit-dev mariadb-client nodejs npm \
&& apt-get install -y --no-install-recommends libmagickwand-dev \
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install -j4 gd mcrypt xsl zip intl gettext soap pdo_pgsql pdo_mysql mysqli pgsql json readline opcache \
&& pecl install geoip-1.1.1 redis imagick mongodb \
&& docker-php-ext-enable geoip redis imagick mongodb
RUN { \
echo 'opcache.memory_consumption=128'; \
echo 'opcache.interned_strings_buffer=8'; \
echo 'opcache.max_accelerated_files=4000'; \
echo 'opcache.revalidate_freq=60'; \
echo 'opcache.fast_shutdown=1'; \
echo 'opcache.enable_cli=1'; \
} >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini
echo 'opcache.memory_consumption=128'; \
echo 'opcache.interned_strings_buffer=8'; \
echo 'opcache.max_accelerated_files=4000'; \
echo 'opcache.revalidate_freq=60'; \
echo 'opcache.fast_shutdown=1'; \
echo 'opcache.enable_cli=1'; \
} >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini
COPY zz-logformat.conf /usr/local/etc/php-fpm.d/
COPY php.ini /usr/local/etc/php/conf.d/
RUN (curl --silent --show-error https://getcomposer.org/installer | php) \
&& mv composer.phar /usr/local/bin/composer
&& mv composer.phar /usr/local/bin/composer
RUN curl --location --silent --show-error https://symfony.com/installer -o /usr/local/bin/symfony \
&& chmod a+x /usr/local/bin/symfony
&& chmod a+x /usr/local/bin/symfony
RUN curl --location --silent --show-error https://s3.amazonaws.com/files.drush.org/drush.phar -o /usr/local/bin/drush \
&& chmod a+x /usr/local/bin/drush
&& chmod a+x /usr/local/bin/drush
RUN (npm install -g uglify-js) \
&& ln -s /usr/bin/nodejs /usr/local/bin/node
RUN (npm install -g uglify-es) \
&& ln -s /usr/bin/nodejs /usr/local/bin/node
RUN apt-get clean \
&& rm -rf /var/lib/apt/lists/
&& rm -rf /var/lib/apt/lists/
+3 -3
View File
@@ -1,4 +1,4 @@
FROM php:7.1-fpm
FROM php:7.1-fpm-buster
ENV TERM=xterm
@@ -10,7 +10,7 @@ RUN echo 'fr_FR.UTF-8 UTF-8' > /etc/locale.gen \
&& /usr/sbin/locale-gen
RUN apt-get update \
&& apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libpng12-dev libmcrypt-dev libxslt-dev libicu-dev libxml2-dev libpq-dev libgeoip-dev libedit-dev mysql-client \
&& apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libpng-dev libmcrypt-dev libxslt-dev libicu-dev libxml2-dev libpq-dev libgeoip-dev libedit-dev mariadb-client \
&& apt-get install -y --no-install-recommends libmagickwand-dev \
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install -j4 gd mcrypt xsl zip intl gettext soap pdo_pgsql pdo_mysql mysqli pgsql json readline opcache \
@@ -33,4 +33,4 @@ RUN (curl --silent --show-error https://getcomposer.org/installer | php) \
&& mv composer.phar /usr/local/bin/composer
RUN apt-get clean \
&& rm -rf /var/lib/apt/lists/
&& rm -rf /var/lib/apt/lists/
+35
View File
@@ -0,0 +1,35 @@
FROM php:7.1-fpm
ENV TERM=xterm
RUN apt-get clean \
&& apt-get update \
&& apt-get install -y lsof nano less git locales
RUN echo 'fr_FR.UTF-8 UTF-8' > /etc/locale.gen \
&& /usr/sbin/locale-gen
RUN apt-get update \
&& apt-get install -y libfreetype6-dev libjpeg62-turbo-dev libpng-dev libmcrypt-dev libxslt-dev libicu-dev libxml2-dev libpq-dev libgeoip-dev libedit-dev mysql-client \
&& apt-get install -y --no-install-recommends libmagickwand-dev \
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install -j4 gd mcrypt xsl zip intl gettext soap pdo_pgsql pdo_mysql mysqli pgsql json readline opcache \
&& pecl install geoip-1.1.1 redis imagick \
&& docker-php-ext-enable geoip redis imagick
RUN { \
echo 'opcache.memory_consumption=128'; \
echo 'opcache.interned_strings_buffer=8'; \
echo 'opcache.max_accelerated_files=4000'; \
echo 'opcache.revalidate_freq=60'; \
echo 'opcache.fast_shutdown=1'; \
echo 'opcache.enable_cli=1'; \
} >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini
COPY zz-logformat.conf /usr/local/etc/php-fpm.d/
COPY php.ini /usr/local/etc/php/conf.d/
RUN (curl --silent --show-error https://getcomposer.org/installer | php) \
&& mv composer.phar /usr/local/bin/composer
RUN apt-get clean \
&& rm -rf /var/lib/apt/lists/
+7
View File
@@ -0,0 +1,7 @@
date.timezone = Europe/Paris
display_errors = Off
memory_limit = 256M
log_errors = On
error_reporting = E_ALL
error_log = /dev/stdout
report_memleaks = On
@@ -0,0 +1,2 @@
[www]
access.format = "%R [%t] \"%m %r%Q%q\" %s %f %{mili}dms %{kilo}MKb %C%%"
+55
View File
@@ -0,0 +1,55 @@
FROM php:7.1-fpm
ENV TERM=xterm
#RUN echo 'deb http://ftp.debian.org/debian jessie-backports main' > /etc/apt/sources.list.d/debian-backports.list
RUN printf "deb http://archive.debian.org/debian/ jessie main\ndeb-src http://archive.debian.org/debian/ jessie main\ndeb http://security.debian.org jessie/updates main\ndeb-src http://security.debian.org jessie/updates main" > /etc/apt/sources.list.d/debian-backports.list
RUN apt-get clean \
&& apt-get update \
&& apt-get install -y lsof nano less git locales
RUN echo 'fr_FR.UTF-8 UTF-8' > /etc/locale.gen \
&& /usr/sbin/locale-gen
RUN apt-get update && apt-get install -my wget gnupg
RUN curl -sL https://deb.nodesource.com/setup_9.x | bash - \
&& apt-get install -y nodejs
RUN apt-get update \
&& apt-get install -y ffmpeg exiftool graphviz libfreetype6-dev libjpeg62-turbo-dev libpng-dev libmcrypt-dev libxslt-dev libicu-dev libxml2-dev libpq-dev libgeoip-dev libedit-dev mysql-client libgmp-dev nodejs \
&& apt-get install -y --no-install-recommends libmagickwand-dev \
&& docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
&& docker-php-ext-install -j4 gd mcrypt xsl zip intl gettext soap pdo_pgsql pdo_mysql mysqli pgsql json readline opcache gmp \
&& docker-php-ext-configure gmp \
&& pecl install geoip-1.1.1 redis imagick mongodb \
&& docker-php-ext-enable geoip redis imagick mongodb
RUN { \
echo 'opcache.memory_consumption=128'; \
echo 'opcache.interned_strings_buffer=8'; \
echo 'opcache.max_accelerated_files=4000'; \
echo 'opcache.revalidate_freq=60'; \
echo 'opcache.fast_shutdown=1'; \
echo 'opcache.enable_cli=1'; \
} >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini
COPY zz-logformat.conf /usr/local/etc/php-fpm.d/
COPY php.ini /usr/local/etc/php/conf.d/
RUN (curl --silent --show-error https://getcomposer.org/installer | php) \
&& mv composer.phar /usr/local/bin/composer
RUN curl --location --silent --show-error https://symfony.com/installer -o /usr/local/bin/symfony \
&& chmod a+x /usr/local/bin/symfony
RUN curl --location --silent --show-error https://s3.amazonaws.com/files.drush.org/drush.phar -o /usr/local/bin/drush \
&& chmod a+x /usr/local/bin/drush
RUN (npm install -g uglify-es) \
&& ln -s /usr/bin/nodejs /usr/local/bin/node
RUN apt-get clean \
&& rm -rf /var/lib/apt/lists/
+9
View File
@@ -0,0 +1,9 @@
date.timezone = Europe/Paris
display_errors = Off
memory_limit = 768M
log_errors = On
error_reporting = E_ALL
error_log = /dev/stdout
report_memleaks = On
upload_max_filesize = 512M
post_max_size = 512M
+2
View File
@@ -0,0 +1,2 @@
[www]
access.format = "%R [%t] \"%m %r%Q%q\" %s %f %{mili}dms %{kilo}MKb %C%%"
+75
View File
@@ -0,0 +1,75 @@
version: "3"
services:
##
## WEBSITE RESSOURCES
##
nginx:
build: build/nginx
container_name: ${CLIENT}.nginx.${ENV}
hostname: nginx
volumes:
- ../volume/nginx/etc.nginx.sites-enabled:/etc/nginx/sites-enabled
- ../volume/www:/home/www
restart: always
php:
build: build/php_win
container_name: ${CLIENT}.php.${ENV}
hostname: php
volumes:
- ../volume/www:/home/www
restart: always
postgres:
image: postgres:9.6
container_name: ${CLIENT}.postgres.${ENV}
hostname: postgres
env_file: env/postgres.env
volumes:
- tt-postgres:/var/lib/postgresql/data
restart: always
mongo:
image: mongo:3.4
container_name: ${CLIENT}.mongo.${ENV}
hostname: mongo
volumes:
- tt-mongo:/data/db
restart: always
elasticsearch:
build: build/elasticsearch
container_name: ${CLIENT}.elasticsearch.${ENV}
hostname: elasticsearch
volumes:
- search_db_data:/usr/share/elasticsearch/data
restart: always
##
## STORE RESSOURCES
##
store-php:
build: build/php_light_win
container_name: ${CLIENT}.store-php.${ENV}
hostname: store-php
volumes:
- ../volume/www:/home/www
restart: always
store-mysql:
build: build/mysql
container_name: ${CLIENT}.store-mysql.${ENV}
hostname: store-mysql
env_file: env/store-mysql.env
volumes:
- ../volume/store-mysql/var.lib.mysql:/var/lib/mysql
restart: always
# Elastic does not play well with physical volume (folder rights trouble)
volumes:
? search_db_data
tt-postgres:
external: true
tt-mongo:
external: true
-4
View File
@@ -1,4 +0,0 @@
MYSQL_ROOT_PASSWORD=
MYSQL_DATABASE=database
MYSQL_USER=user
MYSQL_PASSWORD=
-3
View File
@@ -1,3 +0,0 @@
POSTGRES_USER=
POSTGRES_PASSWORD=
POSTGRES_DB=
+1
View File
@@ -1 +1,2 @@
conf/nginx.conf
/vendor/
+49
View File
@@ -2,3 +2,52 @@ tt
==
A Symfony project created on February 23, 2017, 1:42 pm.
## To have a representation of entity's mappings
In php container, do php bin/console yuml:mappings
To personnalize, see https://github.com/Nono1971/doctrine-yuml-bundle
## If memory issues when installing bundle
Copy this before composer require : COMPOSER_MEMORY_LIMIT=-1
## To update database schema
In php container, root@php:/home/www/website/www# php bin/console doctrine:schema:update --force
It'll update database based on entities
## For Js : use assetic commande inside server container
- do a cache-clear to update the assectic.yml file
bin/console cache:clear --env=prod --no-debug
- then
php bin/console assetic:dump --env=prod --no-debug
## To push notifications
- Create new .json file in web/push folder.
- This file is composed of two arrays : parameters, where you select specific subscribers to receive notifications,
and notification, where you write the content.
- Values for parameters :
* "pushType" : define the rule to find subscribers, only one value which fits with next ones. Values : "general", "profil", "users", "tags".
* "profilCompletenessPercentage" : define the % of profil completeness. Works with "profil" value of pushType.
* "users" : enters subscriber's mail. Works with "users" value of pushType.
* "keywords" : enters tags to identify subscribers. Works with "tags" value of pushType.
- Values for notification :
* "title" : the title!
* "body" : the content.
* "icon" : the website icon.
* "image" : to add an image.
* "tag" : Used to regroup notifications.
* "data" : array where you can add "link" property. Link will redirect to the given URL.
* "actions" : array where you can add specific action with "action", "title".
* "badge" : to add an image for small device.
- Open SendPushCommand.php, go to configure(), and change the last line of addOption() for files with your filename.
## Stacktrace exception API
All exceptions catched are written in the dev.log file (for ENV=dev I guess) in the AppBundle/var/logs folder.
To have an exception that can be written in this file, create or use an already existing Exception (in AppBundle/Exception) in your Controller.
## Question to ask to Corentin
* Is there a validation from Talents Tube operator to set the answer status to published?
* Is there a comment to be written when post an answer ? (not here in mock-up)
+13
View File
@@ -49,8 +49,20 @@ class AppKernel extends Kernel
new Http\HttplugBundle\HttplugBundle(),
new HWI\Bundle\OAuthBundle\HWIOAuthBundle(),
//bentools push
new BenTools\WebPushBundle\WebPushBundle(),
//CookieBar
new Fairlane\CookieConsentBundle\FairlaneCookieConsentBundle(),
//Api
new JMS\SerializerBundle\JMSSerializerBundle(),
new FOS\RestBundle\FOSRestBundle(),
new WhiteOctober\PagerfantaBundle\WhiteOctoberPagerfantaBundle(),
new Bazinga\Bundle\HateoasBundle\BazingaHateoasBundle(),
new Lexik\Bundle\JWTAuthenticationBundle\LexikJWTAuthenticationBundle(),
//CORS
new Nelmio\CorsBundle\NelmioCorsBundle(),
];
if (in_array($this->getEnvironment(), ['dev', 'test'], true)) {
@@ -59,6 +71,7 @@ class AppKernel extends Kernel
$bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();
$bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle();
$bundles[] = new Alex\DoctrineExtraBundle\AlexDoctrineExtraBundle();
$bundles[] = new Onurb\Bundle\YumlBundle\OnurbYumlBundle();
}
return $bundles;
@@ -166,6 +166,10 @@
<source>company.account.password.modify.label</source>
<target>Modifier le mot de passe</target>
</trans-unit>
<trans-unit id="company.account.notifications.title">
<source>company.account.notifications.title</source>
<target>Notifications</target>
</trans-unit>
<trans-unit id="profile.edit.submit">
<source>profile.edit.submit</source>
<target>Sauvegarder mon profil</target>
+52 -2
View File
@@ -14,7 +14,28 @@
{% endblock %}
{% block content %}
{{ form_start(formUser, {'id': 'formUser'}) }}
<div class="row">
<div class="col-xs-8">
<div class="box box-primary">
<div class="box-header">
<h3 class="box-title">Compte utilisateur</h3>
</div>
<div class="box-body">
{{ form_errors(formUser) }}
{{ form_label(formUser.email, 'Email') }}
{{ form_widget(formUser.email, {'attr': {'class': 'form-control'}}) }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-6">
<button class="btn btn-success edit-email-user" data-toggle="tooltip" type="submit">Enregistrer</button>
</div>
</div>
{{ form_end(formUser) }}
<br/>
{{ form_start(form) }}
<div class="row">
<div class="col-xs-8">
@@ -37,7 +58,6 @@
{{ form_row(form.website) }}
{{ form_row(form.tagsComma) }}
{{ form_row(form.file) }}
</div>
</div>
</div>
@@ -66,3 +86,33 @@
{{ form_end(form) }}
{% endblock %}
{% block javascripts %}
<script>
$(document).ready(function () {
$('[data-toggle="popover"]').popover();
$(".edit-email-user").confirm({
title: "Êtes vous sûr de modifier l'adresse mail de cet utilisateur ?",
content: "Si une erreur de saisie est présente, l'utilisateur ne pourra plus recevoir vos mails.",
type: 'ored',
boxWidth: '30%',
useBootstrap: false,
buttons: {
confirm: {
text: 'Confirmer',
action: function() {
$("[name='user_company']").submit();
return true;
}
},
cancel: {
text: 'Annuler'
}
}
});
});
</script>
{% endblock %}
@@ -24,7 +24,7 @@
<div class="col-content bg-arrow z-depth-2 p-20">
<div class="row">
<div class="col s12">
<h4 class="color-blue1 p-0"><span class="title-bubble">1</span> Enregistrez votre cv vidéo</h4>
<h4 class="color-blue1 p-0"><span class="title-bubble">1/3</span> Enregistrez votre cv vidéo</h4>
</div>
<div class="col m4 offset-m1 s12">
<video id="myCvVideo" class="video-js vjs-default-skin"></video>
@@ -60,7 +60,7 @@
<div class="col-content bg-arrow z-depth-2 p-20">
<div class="row">
<div class="col s12">
<h4 class="color-blue1 p-0"><span class="title-bubble">2</span> Importez votre CV Vidéo</h4>
<h4 class="color-blue1 p-0"><span class="title-bubble">2/3</span> Importez votre CV Vidéo</h4>
</div>
<div class="col s10 offset-s1 answer-dropzone">
{% include 'media/dropzone.html.twig' with {'deleting': true } %}
@@ -72,7 +72,7 @@
{{ form_row(form.status) }}
<div class="row">
<div class="col s12">
<h4 class="color-blue1 p-0"><span class="title-bubble">3</span> Ajoutez votre commentaire</h4>
<h4 class="color-blue1 p-0"><span class="title-bubble">3/3</span> Ajoutez votre commentaire</h4>
</div>
<div class="col s10 offset-s1">
<div class="row">
@@ -3,20 +3,11 @@
<head>
<!-- Google Tag Manager -->
<script>
(function (w, d, s, l, i) {
w[l] = w[l] || [];
w[l].push({
'gtm.start': new Date().getTime(), event: 'gtm.js'
});
var f = d.getElementsByTagName(s)[0],
j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : '';
j.async = true;
j.src =
'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
f.parentNode.insertBefore(j, f);
})(window, document, 'script', 'dataLayer', 'GTM-P4G65WJ');
</script>
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-P4G65WJ');</script>
<!-- End Google Tag Manager -->
<script type="text/javascript" defer="defer" src="https://extend.vimeocdn.com/ga/64189815.js"></script>
@@ -70,6 +61,7 @@
{#{% include 'default/alert.html.twig' %}#}
{% include 'default/user_switch.html.twig' %}
{% include 'default/header.html.twig' %}
{% include 'default/props_settings.html.twig' %}
{% block content %}
{% endblock %}
{% include 'default/footer.html.twig' %}
@@ -79,6 +71,7 @@
'@global'
output='assetic/main.js' filter='?uglifyjs2' %}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
{% endblock %}
{{ include('FairlaneCookieConsentBundle::cookie-info.html.twig') }}
@@ -3,20 +3,11 @@
<head>
<!-- Google Tag Manager -->
<script>
(function (w, d, s, l, i) {
w[l] = w[l] || [];
w[l].push({
'gtm.start': new Date().getTime(), event: 'gtm.js'
});
var f = d.getElementsByTagName(s)[0],
j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : '';
j.async = true;
j.src =
'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
f.parentNode.insertBefore(j, f);
})(window, document, 'script', 'dataLayer', 'GTM-P4G65WJ');
</script>
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-P4G65WJ');</script>
<!-- End Google Tag Manager -->
<script type="text/javascript" defer="defer" src="https://extend.vimeocdn.com/ga/64189815.js"></script>
@@ -65,6 +56,7 @@
'@global'
output='assetic/main.base.dash.js' filter='?uglifyjs2' %}
<script src="{{ asset_url }}"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDYV8IJGtIoWLfXJQQvIuDQ88n2aEuRgpg&libraries=places"></script>
{% endjavascripts %}
{% endblock %}
</body>
@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<!-- Title -->
<title>Creative Agency | Space - Responsive Website Template</title>
<!-- Required Meta Tags Always Come First -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Google Fonts -->
<link href="//fonts.googleapis.com/css?family=Roboto:300,400,500,700" rel="stylesheet">
<!-- CSS Implementing Plugins -->
<link rel="stylesheet" href="{{ asset('v2/vendor/font-awesome/css/all.min.css') }}">
<link rel="stylesheet" href="{{ asset('v2/vendor/hs-megamenu/src/hs.megamenu.css') }}">
<link rel="stylesheet" href="{{ asset('v2/vendor/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.css') }}">
<link rel="stylesheet" href="{{ asset('v2/vendor/custombox/dist/custombox.min.css') }}">
<link rel="stylesheet" href="{{ asset('v2/vendor/animate.css/animate.min.css') }}">
<link rel="stylesheet" href="{{ asset('v2/vendor/slick-carousel/slick/slick.css') }}">
<link rel="stylesheet" href="{{ asset('v2/vendor/cubeportfolio/css/cubeportfolio.min.css') }}">
<link rel="stylesheet" href="{{ asset('v2/vendor/fancybox/jquery.fancybox.css') }}">
<!-- CSS Space Template -->
<link rel="stylesheet" href="{{ asset('v2/css/theme.css') }}">
<script type="text/javascript"> window.$crisp=[];window.CRISP_WEBSITE_ID="78ec5756-1cd5-4f3f-b0db-cb408c8171da";(function(){ d=document;s=d.createElement("script"); s.src="https://client.crisp.chat/l.js"; s.async=1;d.getElementsByTagName("head")[0].appendChild(s);})(); </script>
</head>
<body>
<!-- Google Tag Manager (noscript) -->
<noscript>
<iframe src="https://www.googletagmanager.com/ns.html?id=GTM-P4G65WJ"
height="0" width="0" style="display:none;visibility:hidden"></iframe>
</noscript>
<!-- End Google Tag Manager (noscript) -->
{#{% include 'default/alert.html.twig' %}#}
{# {% include 'defaultv2/user_switch.html.twig' %}#}
{% include 'defaultv2/header.html.twig' %}
{#{% include 'defaultv2/props_settings.html.twig' %} #}
{% block content %}
{% endblock %}
{# {% include 'defaultv2/footer.html.twig' %} #}
{{ include('FairlaneCookieConsentBundle::cookie-info.html.twig') }}
</body>
</html>
@@ -40,7 +40,7 @@
{% else %}#}
<div class="embed-responsive embed-responsive-16by9">
<div class="col s12">
<iframe src="https://player.vimeo.com/video/{{ ad.video.cdnUrl|replace({ "/videos/": ""}) }}"
<iframe src="https://player.vimeo.com/video/{{ ad.video.cdnUrl|replace({ "/videos/": ""}) }}?texttrack=fr"
width="100%" height="640" frameborder="0" webkitallowfullscreen mozallowfullscreen
allowfullscreen></iframe>
</div>
@@ -194,6 +194,10 @@
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDYV8IJGtIoWLfXJQQvIuDQ88n2aEuRgpg&libraries=places"></script>
<script type="text/javascript">
$(document).ready(function(){
//asking for push
EdeclicLib = window.EdeclicLib || {};
EdeclicLib.delayedAsk();
//
$('.tooltipped').tooltip();
$.get( "{{ path('ad_ajaxRecStat',{'id': ad.id }) }}", function( data ) {});
if ($('#modal-answer').length > 0) {
@@ -13,15 +13,17 @@
{% else %}
<div class="header-link header-link-signin right-align">
{% if is_granted('ROLE_TALENT') %}
{% set path = path('talent_dashboard') %}
{% set pathDash = path('talent_dashboard') %}
{% elseif is_granted('ROLE_COMPANY') %}
{% set path = path('company_dashboard') %}
{% set pathDash = path('company_dashboard') %}
{% elseif is_granted('ROLE_TERRITORY') %}
{% set path = path('territory_dashboard') %}
{% set pathDash = path('territory_dashboard') %}
{% elseif is_granted('ROLE_ADMIN') %}
{% set path = path('admin_dashboard') %}
{% set pathDash = path('admin_dashboard') %}
{% else %}
{% set pathDash = path('talent_dashboard') %}
{% endif %}
<a class="btn button-round-small" href="{{ path }}">
<a class="btn button-round-small" href="{{ pathDash }}">
<i class="material-icons">perm_identity</i>
<span>Mon compte</span>
</a>
@@ -4,7 +4,7 @@
{% set destination = path('redirect_dashboard') %}
{% endif %}
<a class="btn btn-default btn-facebook z-depth-2" href="{{ url("hwi_oauth_service_redirect", {service: "facebook"}) }}?_destination={{ destination }}">Connexion avec Facebook</a>
<a class="btn btn-default btn-linkedin z-depth-2" href="{{ url("hwi_oauth_service_redirect", {service: "linkedin"}) }}?_destination={{ destination }}">Connexion avec Linkedin</a>
{# <a class="btn btn-default btn-linkedin z-depth-2" href="{{ url("hwi_oauth_service_redirect", {service: "linkedin"}) }}?_destination={{ destination }}">Connexion avec Linkedin</a> #}
<div class="row">
<div class="col s12">
<div class="separator-with-label">
@@ -3,23 +3,49 @@
<div class="row">
<div class="col s12 m12 l10">
<ul id='dropdown_talents' class='dropdown-content'>
<li><a href="{{ path('ad_search_result') }}" title="Offres d'emploi vidéos">Offres d'emploi</a></li>
<li><a href="{{ path('page_cvVideo') }}" title="Le Cv vidéo">Le CV vidéo</a></li>
<li><a href="{{ path('page_reussirCVvideo') }}" title="Comment faire son CV Vidéo ?">Comment faire son CV Vidéo ?</a></li>
<li><a href="{{ path('page_accompagnementTalent') }}" title="Accompagnement talent">Accompagnement</a></li>
<li><a href="{{ path('talent_cv_import') }}" title="Créer mon CV vidéo">Créer mon CV vidéo</a></li>
<li>
<a href="{{ path('ad_search_result') }}" title="Offres d'emploi vidéos">Offres d'emploi</a>
</li>
<li>
<a href="{{ path('page_cvVideo') }}" title="Le Cv vidéo">Le CV vidéo</a>
</li>
<li>
<a href="{{ path('page_reussirCVvideo') }}" title="Comment faire son CV Vidéo ?">Comment faire son CV Vidéo ?</a>
</li>
<li>
<a href="{{ path('page_accompagnementTalent') }}" title="Accompagnement talent">Accompagnement</a>
</li>
<li>
<a href="{{ path('talent_cv_import') }}" title="Créer mon CV vidéo">Créer mon CV vidéo</a>
</li>
</ul>
<ul id='dropdown_company' class='dropdown-content'>
<li><a href="{{ path('company_list') }}" title="Les entreprises qui recrutent">Les entreprises qui recrutent</a></li>
<li><a href="{{ path('page_OffreEmploi') }}" title="L'offre d'emploi en vidéo">L'offre d'emploi en vidéo</a></li>
<li><a href="{{ path('page_reussirOffrevideo') }}" title="Comment faire une offre en vidéo">Comment faire une offre en vidéo</a></li>
<li><a href="{{ path('page_MarqueEmployeur') }}" title="Vidéo Marque Employeur">Vidéo Marque Employeur</a></li>
<li><a href="{{ path('page_accompagnementEntreprise') }}" title="Conseils & accompagnement">Conseils & accompagnement</a></li>
<li>
<a href="{{ path('company_list') }}" title="Les entreprises qui recrutent">Les entreprises qui recrutent</a>
</li>
<li>
<a href="{{ path('page_OffreEmploi') }}" title="L'offre d'emploi en vidéo">L'offre d'emploi en vidéo</a>
</li>
<li>
<a href="{{ path('page_reussirOffrevideo') }}" title="Comment faire une offre en vidéo">Comment faire une offre en vidéo</a>
</li>
<li>
<a href="{{ path('page_MarqueEmployeur') }}" title="Vidéo Marque Employeur">Vidéo Marque Employeur</a>
</li>
<li>
<a href="{{ path('page_accompagnementEntreprise') }}" title="Conseils & accompagnement">Conseils & accompagnement</a>
</li>
</ul>
<ul id='dropdown_territoire' class='dropdown-content'>
<li><a href="{{ path('territory_list') }}">Liste des territoires</a></li>
<li><a href="{{ path('page_VideoTerritory') }}">La vidéo territoire</a></li>
<li><a href="{{ path('page_AccompagnementTerritory') }}">Conseils et accompagnement</a></li>
<li>
<a href="{{ path('territory_list') }}">Liste des territoires</a>
</li>
<li>
<a href="{{ path('page_VideoTerritory') }}">La vidéo territoire</a>
</li>
<li>
<a href="{{ path('page_AccompagnementTerritory') }}">Conseils et accompagnement</a>
</li>
</ul>
<nav>
<div class="nav-wrapper">
@@ -28,16 +54,25 @@
<img src="{{ asset('img/Logo-header.png') }}" alt="Talents Tube"/>
</a>
</div>
<a href="#" data-activates="mobile-demo" class="button-collapse"><i class="material-icons">menu</i></a>
<a href="#" data-activates="mobile-demo" class="button-collapse">
<i class="material-icons">menu</i>
</a>
<ul class="right hide-on-med-and-down">
<li><a class="dropdown-button" data-activates="dropdown_talents" href="{{ path('page_cvVideo') }}"
title="Talents">Talents</a></li>
<li><a href="{{ path('ad_search_result') }}" title="Offres d'emploi vidéos">Offres d'emploi</a></li>
<li><a class="dropdown-button" data-activates="dropdown_company" href="{{ path('company_list') }}"
title="Les entreprises de talents">Entreprises</a></li>
<li><a class="dropdown-button" data-activates="dropdown_territoire" href="{{ path('territory_list') }}"
title="Les territoires">Territoires</a></li>
<li><a href="https://blog.talentstube.com" title="Blog Talents Tube">Blog</a></li>
<li>
<a class="dropdown-button" data-activates="dropdown_talents" href="{{ path('page_cvVideo') }}" title="Talents">Talents</a>
</li>
<li>
<a href="{{ path('ad_search_result') }}" title="Offres d'emploi vidéos">Offres d'emploi</a>
</li>
<li>
<a class="dropdown-button" data-activates="dropdown_company" href="{{ path('company_list') }}" title="Les entreprises de talents">Entreprises</a>
</li>
<li>
<a class="dropdown-button" data-activates="dropdown_territoire" href="{{ path('territory_list') }}" title="Les territoires">Territoires</a>
</li>
<li>
<a href="https://blog.talentstube.com" title="Blog Talents Tube">Blog</a>
</li>
</ul>
</div>
@@ -48,6 +83,13 @@
</div>
</div>
</div>
<div id="newApp" class="container-fluid">
<div class="row">
<div class="col s12 m12">
<p>"Nouveau ! Trouvez un job plus facilement avec notre <a href="http://app.talentstube.com">web application</a>.📲"</p>
</div>
</div>
</div>
</div>
<div class="nav-wrapper">
<ul class="side-nav collapsible" data-collapsible="accordion" id="mobile-demo">
@@ -94,4 +136,4 @@
<a class="collapsible-header" href="https://blog.talentstube.com" title="Blog Talents Tube">Blog</a>
</li>
</ul>
</div>
</div>
@@ -19,7 +19,7 @@
</div>
<div class="header-video-inner">
<video loop="" preload="metadata" autoplay="" id="vid" muted="muted">
<source src="/img/home_video.mp4" type="video/mp4">
<source src="/img/home_video.mp4" type="video/mp4">
</video>
</div>
@@ -112,7 +112,7 @@
</div>
</div>
<div class="row center-align">
<h2>Rejoignez une communauté de plus de <strong>500</strong> candidats</h2>
<h2>Rejoignez une communauté de plus de <strong>1000</strong> candidats</h2>
<div class="col s12 m-t-50">
<a href="#!" title="Créer Mon profil" class="btn btn-default btn-round btn-create-account">Créer mon profil</a>
</div>
@@ -0,0 +1,10 @@
<!-- props_settings.html.twig Parameters used in EdeclicPushAndNotificationClient.js -->
<div id="pushParams"
data-service-worker-url="{{ app.request.uriForPath('/Edeclic-service-worker.js') | replace({'/app_dev.php': ''}) }}"
data-analytics-helper-url="{{ app.request.uriForPath('js/analytics-helper.js') | replace({'/app_dev.php': ''}) }}"
data-delete-subscription-url="{{ url('delete-subscription') }}"
data-save-subscription-url="{{ url('save-subscription') }}"
data-push-public-key="{{ push_public_key }}"
>
</div>
@@ -0,0 +1,31 @@
<!-- Candidat DEBUT -->
<div class="space-1-bottom accueilFondNoir">
<div class="container space-2 ">
<div class="row align-items-lg-center">
<div class="col-md-6 order-md-2 mb-5 mb-md-0">
<!-- Title -->
<div class="mb-4">
<h2 class="h3"> Recevez les candidatures en vidéo</h2>
<p> Depuis leur webcam, smartphone ou tablette, les candidats postulent aux vidéos de votre entreprise, en
toute confidentialité, grâce à notre outil denregistrement vidéo simple, rapide et gratuit.
Vous recevez des vidéos de motivation, cest-à-dire des candidatures qui répondent à votre vidéo de
recrutement. Le candidat expose son parcours en illustrant ses expériences. Il met en avant ses
motivations à vous rejoindre et les compétences quil peut apporter à votre entreprise.
<strong>Découvrez la personnalité du candidat et son projet professionnel en quelques instants.</strong>
</p>
<a class="btn btn-sm btn-primary btn-wide" href="#">En savoir plus</a>
</div>
</div>
<div class="col-md-6 order-md-1">
<div class="pr-lg-4">
<img class="img-fluid" src="{{ asset('v2/png/candidature-en-video.png') }}" alt="Image Description">
</div>
</div>
</div>
</div>
</div>
<!-- Candidat FIN -->
@@ -0,0 +1,40 @@
<!-- Ils nous font confiance DEBUT -->
<div class="container space-2 space-3--lg accueilFondBlanc">
<div class=" text-center mx-md-auto mb-12">
<!-- Title -->
<h2 class="h1"> Ils nous font confiance</h2>
<!-- Slick Carousel -->
<div class="js-slick-carousel u-slick" data-autoplay="true" data-speed="5000" data-infinite="true"
data-slides-show="5">
<div class="js-slide">
<img src="{{ asset('v2/logos/Albea-logo.png') }}" alt="Image Description">
</div>
<div class="js-slide">
<img src="{{ asset('v2/logos/Bouyer-leroux-logo.png') }}" alt="Image Description">
</div>
<div class="js-slide">
<img src="{{ asset('v2/logos/Eiffage-logo.png') }}" alt="Image Description">
</div>
<div class="js-slide">
<img src="{{ asset('v2/logos/groupe-mousset-logo.png') }}" alt="Image Description">
</div>
<div class="js-slide">
<img src="{{ asset('v2/logos/Groupe-rocher-logo.png') }}" alt="Image Description">
</div>
<div class="js-slide">
<img src="{{ asset('v2/logos/intermarche.png') }}" alt="Image Description">
</div>
<div class="js-slide">
<img src="{{ asset('v2/logos/Mazars-logo.png') }}" alt="Image Description">
</div>
<div class="js-slide">
<img src="{{ asset('v2/logos/Mma-logo.png') }}" alt="Image Description">
</div>
<div class="js-slide">
<img src="{{ asset('v2/logos/Square-habitat-logo.png') }}" alt="Image Description">
</div>
</div>
<!-- End Slick Carousel -->
</div>
</div>
<!-- Ils nous font confiance FIN -->
@@ -0,0 +1,87 @@
<!-- Degradé avec Stats Section -->
<div class="gradient-overlay-half-primary-v1">
<div class="bg-img-hero" style="background-image: url({{ asset('v2/img/bg/bg2.png')}} ">
<div class="container space-2 space-3--lg ">
<div class="container position-relative z-index-2 containerStat">
<div class="bg-gray-100 shadow-lg rounded mt-n9">
<div class="card-deck d-block d-lg-flex">
<div class="card card-frame mb-4 mb-lg-0">
<!-- Listing -->
<div class="card-body p-4">
<div class="media">
<div class="media-body px-4">
<h2 class="statChiffre">1500+</h2>
<p class="statTexte">Talents connectés</p>
</div>
</div>
</div>
<!-- End Listing -->
</div>
<div class="card card-frame mb-4 mb-lg-0">
<!-- Listing -->
<div class="card-body p-4">
<div class="media">
<div class="media-body px-4">
<h2 class="statChiffre">900+</h2>
<p class="statTexte">Vues par vidéo</p>
</div>
</div>
</div>
<!-- End Listing -->
</div>
<div class="card card-frame mb-4 mb-lg-0">
<!-- Listing -->
<div class="card-body p-4">
<div class="media">
<div class="media-body px-4">
<h2 class="statChiffre">350</h2>
<p class="statTexte">Candidatures vidéo</p>
</div>
</div>
</div>
<!-- End Listing -->
</div>
</div>
</div>
</div>
</div>
<!-- Icon Blocks Section -->
<div class="container ">
<div class="row">
<div class="col-md-4 mb-7 mb-md-0">
<!-- Icon Blocks -->
<div class="text-center px-lg-3">
<img src="{{ asset('v2/svg/components/Diffusion-offres-emploi-video-marque-employeur.svg') }}" alt="Logo">
<h3 class="h4 text-white">Diffusez vos offres d'emploi et marque employeur en <a href="#">vidéo</a></h3>
</div>
<!-- End Icon Blocks -->
</div>
<div class="col-md-4 mb-7 mb-md-0">
<!-- Icon Blocks -->
<div class="text-center px-lg-3">
<img src="{{ asset('v2/svg/components/Gestion-des-candidatures-video.svg') }}" alt="Logo">
<h3 class="h4 text-white">Recevez les candidatures en <a href="#">vidéo</a></h3>
</div>
<!-- End Icon Blocks -->
</div>
<div class="col-md-4">
<!-- Icon Blocks -->
<div class="text-center px-lg-3">
<img src="{{ asset('v2/svg/components/candidature-en-video.svg') }}" alt="Logo">
<h3 class="h4 text-white">Gérez vos candidatures en <a href="#">vidéo</a></h3>
</div>
<!-- End Icon Blocks -->
</div>
</div>
</div>
<!-- End Icon Blocks Section -->
</div>
</div>
<!-- Degradé avec Stats FIN-->
@@ -0,0 +1,32 @@
<!-- Marque employeur DEBUT -->
<div class="space-1-bottom accueilFondBlanc">
<div class="container space-2 ">
<div class="row align-items-lg-center">
<div class="col-md-6 order-md-2 mb-5 mb-md-0">
<!-- Title -->
<div class="mb-4">
<h2 class="h3"> Révélez votre Marque Employeur en vidéo</h2>
<p> Talents Tube offre une visibilité essentielle à votre marque employeur.
Grâce à la vidéo, votre entreprise replace lhumain au cœur du recrutement. Vous disposez dun levier
concret et efficace pour parfaire votre réputation. Développez lattractivité de votre entreprise pour
séduire de nouveaux talents.
<strong>Donnez vie à votre marque employeur en plaçant la vidéo au coeur de votre stratégie de
communication
et de votre gestion des ressources humaines.</strong>
</p>
<a class="btn btn-sm btn-primary btn-wide" href="#">Voir la plateforme</a>
</div>
</div>
<div class="col-md-6 order-md-1">
<div class="pr-lg-4">
<img class="img-fluid" src="{{ asset('v2/png/marque-employeur-en-video.png') }}" alt="Image Description">
</div>
</div>
</div>
</div>
</div>
<!-- Marque employeur FIN -->
@@ -0,0 +1,20 @@
<!-- Accueil Photo Haut Section -->
<div class="bg-img-hero-center" style="background-image: url({{ asset('v2/img/1920x800/recrutement-video.jpg')}} ">
<div class="container space-2 space-5-top--lg space-4-bottom--lg">
<div class="w-md-75">
<!-- Title -->
<div class="mb-7">
<span class="d-block text-white text-uppercase mb-2">Talents tube</span>
<h1 class="display-4 font-size-48--md-down text-white mb-4">
<strong class="u-text-animation u-text-animation--typing"></strong>
<br>avec la vidéo
</h1>
</div>
<!-- End Title -->
</div>
</div>
</div>
<!-- End Accueil Photo Haut Section -->
@@ -0,0 +1,33 @@
<!-- Plateforme DEBUT -->
<div class="space-1-bottom accueilFondBleute">
<div class="container space-2 ">
<div class="row align-items-lg-center">
<div class="col-lg-5 mb-9 mb-lg-0">
<!-- Title <div class="col-md-6 order-md-2 mb-5 mb-md-0">-->
<div class="mb-4">
<h2 class="h3"> Plateforme pour lemploi 100% vidéo</h2>
<p> Talents Tube met à votre disposition un outil de diffusion de vos vidéos doffres demploi & marque
employeur pour attirer les meilleurs talents en vidéo.
Notre plateforme rassemble lentreprise et les talents qui se présentent en vidéo pour un recrutement
réussi.
Si vous ne possédez pas de vidéos, nous pouvons vous accompagner dans la réalisation.
<strong>Diffusez vos vidéos de recrutement et augmentez votre visibilité.</strong>
</p>
<a class="btn btn-sm btn-primary btn-wide" href="#">Voir la plateforme</a>
</div>
</div>
<div class="col-md-6 order-md-1">
<div class="pr-lg-4">
<img class="img-fluid" src="{{ asset('v2/png/plateforme-de-recrutement-en-video.png') }}"
alt="Image Description">
</div>
</div>
</div>
</div>
</div>
<!-- Plateforme FIN -->
@@ -0,0 +1,32 @@
<!-- Recrutez DEBUT -->
<div class="space-1-bottom accueilFondBleute">
<div class="container space-2 ">
<div class="row align-items-lg-center">
<div class="col-lg-5 mb-9 mb-lg-0">
<!-- Title <div class="col-md-6 order-md-2 mb-5 mb-md-0">-->
<div class="mb-4">
<h2 class="h3"> Recrutez avec des offres demploi vidéo</h2>
<p> alents Tube peut vous accompagner dans la réalisation de vidéos doffres demploi captivantes et à votre
image.
Loffre demploi en vidéo, média engageant, vous donne lopportunité de recruter les meilleurs talents. Le
principe est de donner une image moderne et innovante en présentant votre entreprise, votre équipe,
lenvironnement de travail et le poste à pourvoir en quelques minutes.
<strong>Faites place à linnovation pour capter lattention des candidats et recruter le talent quil vous
faut.</strong>
</p>
<a class="btn btn-sm btn-primary btn-wide" href="#">Voir la plateforme</a>
</div>
</div>
<div class="col-md-6 order-md-1">
<div class="pr-lg-4">
<img class="img-fluid" src="{{ asset('v2/png/offres-emploi-en-video.png') }}" alt="Image Description">
</div>
</div>
</div>
</div>
</div>
<!-- Recrutez FIN -->
@@ -0,0 +1,162 @@
<!-- Témoignage DEBUT -->
<div class="space-2-top space-1-bottom space-3-top--lg accueilFondNoir">
<div class="container">
<!-- Title -->
<div class="w-md-80 w-lg-60 mx-md-auto text-md-center mb-8">
<h6 class="text-uppercase text-gray-700 font-weight-medium letter-spacing-0_06 mb-3"> Ils ont choisi Talents Tube pour recruter différemment.</h6>
<h2 class="text-lh-xs mb-0">Témoignages de nos clients</h2>
</div>
<!-- End Title -->
<!-- Stories -->
<div id="sliderSyncingNav2" class="js-slick-carousel u-slick u-slick--rounded mb-2" data-infinite="true"
data-arrows-classes="d-none d-md-inline-block u-slick__arrow-classic u-slick__arrow-centered--y rounded-circle shadow"
data-arrow-left-classes="fa fa-arrow-left u-slick__arrow-classic-inner bg-white text-dark left-0 ml-md-n9"
data-arrow-right-classes="fa fa-arrow-right u-slick__arrow-classic-inner bg-white text-dark right-0 mr-md-n9"
data-nav-for="#sliderSyncingThumb2">
<div class="js-slide bg-img-hero bg-img-hero-center gradient-overlay-half-black-v1"
style="background-image: url({{ asset('v2/temoignages/mgdis-temoignage-image.jpg') }});">
<div class="w-md-80 w-lg-50 text-white space-2 px-9">
<h3 class="h2 text-lh-xs mb-4">MGDIS</h3>
<p class="text-white-70 mb-4">Simona Vasile-Martin, Responsable Marketing</p>
<a class="js-fancybox text-white" href="javascript:;"
data-src="https://www.youtube.com/watch?v=E62HUkaPEkk&t?autoplay=1"
data-speed="700"
data-animate-in="zoomIn"
data-animate-out="zoomOut"
data-caption="MGDIS"
data-is-infinite=true>
Voir le témoignage
<i class="u-icon u-icon--sm u-icon--white-soft rounded-circle ml-2">
<i class="u-icon__inner svg-icon svg-icon-xs text-white">
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<rect x="0" y="0" width="24" height="24"></rect>
<path d="M9.82866499,18.2771971 L16.5693679,12.3976203 C16.7774696,12.2161036 16.7990211,11.9002555 16.6175044,11.6921539 C16.6029128,11.6754252 16.5872233,11.6596867 16.5705402,11.6450431 L9.82983723,5.72838979 C9.62230202,5.54622572 9.30638833,5.56679309 9.12422426,5.7743283 C9.04415337,5.86555116 9,5.98278612 9,6.10416552 L9,17.9003957 C9,18.1765381 9.22385763,18.4003957 9.5,18.4003957 C9.62084305,18.4003957 9.73759731,18.3566309 9.82866499,18.2771971 Z" fill="#000000"></path>
</g>
</svg>
</i>
</i>
</a>
</div>
</div>
<div class="js-slide bg-img-hero bg-img-hero-center gradient-overlay-half-black-v1"
style="background-image: url({{ asset('v2/temoignages/medaviz-temoignage-image.jpg') }});">
<div class="w-md-80 w-lg-50 text-white space-2 px-9">
<h3 class="h2 text-lh-xs mb-4">Medaviz</h3>
<p class="text-white-70 mb-4">Guillaume Lesdos, Co-fondateur et Président</p>
<a class="js-fancybox text-white" href="javascript:;"
data-src="https://www.youtube.com/watch?v=Em3niStNutA?autoplay=1"
data-speed="700"
data-animate-in="zoomIn"
data-animate-out="zoomOut"
data-caption="Medaviz"
data-is-infinite=true>
Voir le témoignage
<i class="u-icon u-icon--sm u-icon--white-soft rounded-circle ml-2">
<i class="u-icon__inner svg-icon svg-icon-xs text-white">
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<rect x="0" y="0" width="24" height="24"></rect>
<path d="M9.82866499,18.2771971 L16.5693679,12.3976203 C16.7774696,12.2161036 16.7990211,11.9002555 16.6175044,11.6921539 C16.6029128,11.6754252 16.5872233,11.6596867 16.5705402,11.6450431 L9.82983723,5.72838979 C9.62230202,5.54622572 9.30638833,5.56679309 9.12422426,5.7743283 C9.04415337,5.86555116 9,5.98278612 9,6.10416552 L9,17.9003957 C9,18.1765381 9.22385763,18.4003957 9.5,18.4003957 C9.62084305,18.4003957 9.73759731,18.3566309 9.82866499,18.2771971 Z" fill="#000000"></path>
</g>
</svg>
</i>
</i>
</a>
</div>
</div>
<div class="js-slide bg-img-hero bg-img-hero-center gradient-overlay-half-black-v1"
style="background-image: url({{ asset('v2/temoignages/thalazur-carnac1-temoignage-image.jpg') }});">
<div class="w-md-80 w-lg-50 text-white space-2 px-9">
<h3 class="h2 text-lh-xs mb-4">Thalazur Carnac</h3>
<p class="text-white-70 mb-4">Adeline Lautredou, Responsable Ressources Humaines</p>
<a class="js-fancybox text-white" href="javascript:;"
data-src="https://www.youtube.com/watch?v=hWYae9V-YWM&t=8s?autoplay=1"
data-speed="700"
data-animate-in="zoomIn"
data-animate-out="zoomOut"
data-caption="Thalazur Carnac"
data-is-infinite=true>
Voir le témoignage
<i class="u-icon u-icon--sm u-icon--white-soft rounded-circle ml-2">
<i class="u-icon__inner svg-icon svg-icon-xs text-white">
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<rect x="0" y="0" width="24" height="24"></rect>
<path d="M9.82866499,18.2771971 L16.5693679,12.3976203 C16.7774696,12.2161036 16.7990211,11.9002555 16.6175044,11.6921539 C16.6029128,11.6754252 16.5872233,11.6596867 16.5705402,11.6450431 L9.82983723,5.72838979 C9.62230202,5.54622572 9.30638833,5.56679309 9.12422426,5.7743283 C9.04415337,5.86555116 9,5.98278612 9,6.10416552 L9,17.9003957 C9,18.1765381 9.22385763,18.4003957 9.5,18.4003957 C9.62084305,18.4003957 9.73759731,18.3566309 9.82866499,18.2771971 Z" fill="#000000"></path>
</g>
</svg>
</i>
</i>
</a>
</div>
</div>
</div>
<!-- End Stories -->
<!-- Stories.Authors -->
<div id="sliderSyncingThumb2"
class="js-slick-carousel u-slick u-slick--gutters-2 u-slick--video w-50 w-lg-30 mx-auto" data-infinite="true"
data-slides-show="3" data-is-thumbs="true" data-center-mode="true" data-nav-for="#sliderSyncingNav2">
<div class="js-slide rounded overflow-hidden">
<img class="img-fluid" src="{{ asset('v2/temoignages/mgdis-temoignage-vignette.jpg') }}" alt="Image Description">
<i class="u-icon u-icon--sm u-icon--dark-soft rounded-circle u-slick--video__player">
<i class="u-icon__inner svg-icon svg-icon-xs text-white">
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<rect x="0" y="0" width="24" height="24"></rect>
<path
d="M9.82866499,18.2771971 L16.5693679,12.3976203 C16.7774696,12.2161036 16.7990211,11.9002555 16.6175044,11.6921539 C16.6029128,11.6754252 16.5872233,11.6596867 16.5705402,11.6450431 L9.82983723,5.72838979 C9.62230202,5.54622572 9.30638833,5.56679309 9.12422426,5.7743283 C9.04415337,5.86555116 9,5.98278612 9,6.10416552 L9,17.9003957 C9,18.1765381 9.22385763,18.4003957 9.5,18.4003957 C9.62084305,18.4003957 9.73759731,18.3566309 9.82866499,18.2771971 Z"
fill="#000000"></path>
</g>
</svg>
</i>
</i>
</div>
<div class="js-slide rounded overflow-hidden">
<img class="img-fluid" src="{{ asset('v2/temoignages/medaviz-temoignage-vignette.jpg') }}" alt="Image Description">
<i class="u-icon u-icon--sm u-icon--dark-soft rounded-circle u-slick--video__player">
<i class="u-icon__inner svg-icon svg-icon-xs text-white">
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<rect x="0" y="0" width="24" height="24"></rect>
<path
d="M9.82866499,18.2771971 L16.5693679,12.3976203 C16.7774696,12.2161036 16.7990211,11.9002555 16.6175044,11.6921539 C16.6029128,11.6754252 16.5872233,11.6596867 16.5705402,11.6450431 L9.82983723,5.72838979 C9.62230202,5.54622572 9.30638833,5.56679309 9.12422426,5.7743283 C9.04415337,5.86555116 9,5.98278612 9,6.10416552 L9,17.9003957 C9,18.1765381 9.22385763,18.4003957 9.5,18.4003957 C9.62084305,18.4003957 9.73759731,18.3566309 9.82866499,18.2771971 Z"
fill="#000000"></path>
</g>
</svg>
</i>
</i>
</div>
<div class="js-slide rounded overflow-hidden">
<img class="img-fluid" src="{{ asset('v2/temoignages/thalazur-carnac-temoignage-vignette.jpg') }}" alt="Image Description">
<i class="u-icon u-icon--sm u-icon--dark-soft rounded-circle u-slick--video__player">
<i class="u-icon__inner svg-icon svg-icon-xs text-white">
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<rect x="0" y="0" width="24" height="24"></rect>
<path
d="M9.82866499,18.2771971 L16.5693679,12.3976203 C16.7774696,12.2161036 16.7990211,11.9002555 16.6175044,11.6921539 C16.6029128,11.6754252 16.5872233,11.6596867 16.5705402,11.6450431 L9.82983723,5.72838979 C9.62230202,5.54622572 9.30638833,5.56679309 9.12422426,5.7743283 C9.04415337,5.86555116 9,5.98278612 9,6.10416552 L9,17.9003957 C9,18.1765381 9.22385763,18.4003957 9.5,18.4003957 C9.62084305,18.4003957 9.73759731,18.3566309 9.82866499,18.2771971 Z"
fill="#000000"></path>
</g>
</svg>
</i>
</i>
</div>
</div>
<!-- End Stories.Authors -->
</div>
</div>
<!-- End Success stories -->
<!-- Témoignage FIN -->
@@ -0,0 +1,634 @@
{% extends 'basev2.html.twig' %}
{% block title %}Talents Tube : Le 1er job board 100% vidéo{% endblock %}
{% block content %}
<main id="content">
{% include 'defaultv2/accueil/blocPhoto.html.twig' %}
{% include 'defaultv2/accueil/blocDegrade.html.twig' %}
{% include 'defaultv2/accueil/blocPlateforme.html.twig' %}
{% include 'defaultv2/accueil/blocCandidat.html.twig' %}
{% include 'defaultv2/accueil/blocRecrutez.html.twig' %}
{% include 'defaultv2/accueil/blocEmployeur.html.twig' %}
{% include 'defaultv2/accueil/blocTemoignages.html.twig' %}
{% include 'defaultv2/accueil/blocConfiance.html.twig' %}
</main>
<!-- ========== END MAIN CONTENT ========== -->
<!-- ========== FOOTER ========== -->
<footer class="bg-dark">
<div class="container space-2">
<div class="row justify-content-md-between">
<div class="col-6 col-md-3 col-lg-2 order-lg-3 mb-7 mb-lg-0">
<h3 class="h6 text-white mb-3">About</h3>
<!-- List Group -->
<div class="list-group list-group-flush list-group-transparent">
</div>
<!-- End List Group -->
</div>
<div class="col-6 col-md-3 col-lg-2 order-lg-4 mb-7 mb-lg-0">
<h3 class="h6 text-white mb-3">Company</h3>
<!-- List Group -->
<div class="list-group list-group-flush list-group-transparent">
</div>
<!-- End List Group -->
</div>
<div class="col-6 col-md-3 col-lg-2 order-lg-5 mb-7 mb-lg-0">
<h3 class="h6 text-white mb-3">Blog</h3>
<!-- List Group -->
<div class="list-group list-group-flush list-group-transparent">
</div>
<!-- End List Group -->
</div>
<div class="col-6 col-md-3 col-lg-2 order-lg-6 mb-7 mb-lg-0">
<h3 class="h6 text-white mb-3">Social</h3>
<!-- List -->
<div class="list-group list-group-flush list-group-transparent">
<a class="list-group-item list-group-item-action" href="#">
<i class="fab fa-facebook-f min-width-3 text-center mr-2"></i>
Facebook
</a>
</div>
<!-- End List -->
</div>
<div class="col-lg-4 order-lg-1 d-flex align-items-start flex-column">
<!-- Logo -->
<a class="d-inline-block mb-5" href="index.html" aria-label="Space">
<img src="{{ asset('v2/svg/logos/talentstube-logo-mobile.svg') }}" alt="Logo" style="width: 40px; max-width: 100%;">
</a>
<!-- End Logo -->
<p class="small text-muted">Tous droits réservés. &copy; Space. 2020 Talents Tube.</p>
</div>
</div>
</div>
</footer>
<!-- ========== END FOOTER ========== -->
<!-- ========== SECONDARY CONTENTS ========== -->
<!-- Panel Sidebar Navigation -->
<aside id="sidebarContent" class="u-sidebar u-unfold--css-animation u-unfold--hidden"
aria-labelledby="sidebarNavToggler">
<div class="u-sidebar__scroller">
<div class="u-sidebar__container">
<div class="u-sidebar--panel__footer-offset">
<!-- Toggle Button -->
<div class="d-flex align-items-center border-bottom py-4 px-5">
<h4 class="h5 mb-0">Mon compte</h4>
<button type="button" class="close u-sidebar__close ml-auto" aria-controls="sidebarContent"
aria-haspopup="true" aria-expanded="false" data-unfold-event="click" data-unfold-hide-on-scroll="false"
data-unfold-target="#sidebarContent" data-unfold-type="css-animation" data-unfold-animation-in="fadeInRight"
data-unfold-animation-out="fadeOutRight" data-unfold-duration="500">
<span aria-hidden="true">&times;</span>
</button>
</div>
<!-- End Toggle Button -->
<!-- Content -->
<div class="js-scrollbar u-sidebar__body">
<div class="u-sidebar__content py-5">
<!-- Title -->
<div class="py-2 px-5">
<h4 class="text-uppercase text-muted font-size-13 mb-0">Mon menu</h4>
</div>
<!-- End Title -->
<!-- List -->
<ul class="list-unstyled font-size-14 mb-5">
<li>
<a class="media align-items-center u-sidebar--panel__link py-2 px-5" href="#">
<img class="max-width-4 mr-3" src="{{ asset('v2/svg/components/finance-dark-icon.svg') }}"
alt="Image Description">
<div class="media-body">
<span>Dashboard</span>
</div>
</a>
</li>
<li>
<a class="media align-items-center u-sidebar--panel__link py-2 px-5" href="#">
<img class="max-width-4 mr-3" src="{{ asset('v2/svg/components/touch-dark-icon.svg') }}"
alt="Image Description">
<div class="media-body">
<span>Activity</span>
</div>
</a>
</li>
<li>
<a class="media align-items-center u-sidebar--panel__link py-2 px-5" href="#">
<img class="max-width-4 mr-3" src="{{ asset('v2/svg/components/team-dark-icon.svg') }}"
alt="Image Description">
<div class="media-body">
<span>Team</span>
</div>
</a>
</li>
<li>
<a class="media align-items-center u-sidebar--panel__link py-2 px-5" href="#">
<img class="max-width-4 mr-3" src="{{ asset('v2/svg/components/email-dark-icon.svg') }}"
alt="Image Description">
<div class="media-body">
<span>Mailbox</span>
</div>
</a>
</li>
<li>
<a class="media align-items-center u-sidebar--panel__link py-2 px-5" href="#">
<img class="max-width-4 mr-3" src="{{ asset('v2/svg/components/projects-dark-icon.svg') }}"
alt="Image Description">
<div class="media-body">
<span>Projects</span>
</div>
</a>
</li>
</ul>
<!-- End List -->
<!-- Title -->
<div class="py-2 px-5">
<h4 class="text-uppercase text-muted font-size-13 mb-0">Sub level</h4>
</div>
<!-- End Title -->
<!-- List -->
<ul class="list-unstyled font-size-14 mb-0">
<li>
<a class="media align-items-center u-sidebar--panel__link py-2 px-5" href="#">
<img class="max-width-4 mr-3" src="{{ asset('v2/svg/components/calendar-dark-icon.svg') }}"
alt="Image Description">
<div class="media-body">
<span>Calendar</span>
</div>
</a>
</li>
<li>
<a class="media align-items-center u-sidebar--panel__link py-2 px-5" href="#">
<img class="max-width-4 mr-3" src="{{ asset('v2/svg/components/cog-dark-icon.svg') }}"
alt="Image Description">
<div class="media-body">
<span>Tools</span>
</div>
</a>
</li>
<li>
<a class="media align-items-center u-sidebar--panel__link py-2 px-5" href="#">
<img class="max-width-4 mr-3" src="{{ asset('v2/svg/components/archive-dark-icon.svg') }}"
alt="Image Description">
<div class="media-body">
<span>Archive</span>
</div>
</a>
</li>
</ul>
<!-- End List -->
</div>
</div>
<!-- End Content -->
</div>
<!-- Footer -->
<footer class="u-sidebar__footer u-sidebar__footer--panel py-4 px-5">
<!-- List -->
<ul class="list-inline font-size-14 mb-0">
<li class="list-inline-item">
<a class="u-sidebar--panel__link pr-2" href="../pages/privacy.html">Privacy</a>
</li>
<li class="list-inline-item">
<a class="u-sidebar--panel__link px-2" href="../pages/terms.html">Terms</a>
</li>
<li class="list-inline-item">
<a class="u-sidebar--panel__link pl-2" href="../pages/help.html">
<i class="fa fa-info-circle"></i>
</a>
</li>
</ul>
<!-- End List -->
</footer>
<!-- End Footer -->
</div>
</div>
</aside>
<!-- End Panel Sidebar Navigation -->
<!-- Signup Modal Window -->
<div id="signupModal" class="js-signup-modal u-modal-window" style="width: 500px;">
<!-- Modal Close Button -->
<button class="btn btn-sm btn-icon btn-text-secondary u-modal-window__close" type="button"
onclick="Custombox.modal.close();">
<i class="fas fa-times"></i>
</button>
<!-- End Modal Close Button -->
<!-- Content -->
<div class="p-5 bg-white rounded">
<form class="js-validate">
<!-- Signin -->
<div id="signin" data-target-group="idForm">
<!-- Title -->
<header class="text-center mb-5">
<h2 class="h4 mb-0">Please sign in</h2>
<p>Signin to manage your account.</p>
</header>
<!-- End Title -->
<!-- Input -->
<div class="js-form-message mb-3">
<div class="js-focus-state input-group form">
<div class="input-group-prepend form__prepend">
<span class="input-group-text form__text">
<i class="fa fa-user form__text-inner"></i>
</span>
</div>
<input type="email" class="form-control form__input" name="email" required placeholder="Email"
aria-label="Email" data-msg="Please enter a valid email address." data-error-class="u-has-error"
data-success-class="u-has-success">
</div>
</div>
<!-- End Input -->
<!-- Input -->
<div class="js-form-message mb-3">
<div class="js-focus-state input-group form">
<div class="input-group-prepend form__prepend">
<span class="input-group-text form__text">
<i class="fa fa-lock form__text-inner"></i>
</span>
</div>
<input type="password" class="form-control form__input" name="password" required placeholder="Password"
aria-label="Password" data-msg="Your password is invalid. Please try again."
data-error-class="u-has-error" data-success-class="u-has-success">
</div>
</div>
<!-- End Input -->
<div class="row mb-3">
<div class="col-6">
<!-- Checkbox -->
<div class="custom-control custom-checkbox d-flex align-items-center text-muted">
<input type="checkbox" class="custom-control-input" id="rememberMeCheckbox">
<label class="custom-control-label" for="rememberMeCheckbox">
Remember Me
</label>
</div>
<!-- End Checkbox -->
</div>
<div class="col-6 text-right">
<a class="js-animation-link float-right" href="javascript:;" data-target="#forgotPassword"
data-link-group="idForm" data-animation-in="fadeIn">Mot de passe oublié?</a>
</div>
</div>
<div class="mb-3">
<button type="submit" class="btn btn-block btn-primary">Connexion</button>
</div>
<div class="text-center mb-3">
<p class="text-muted">
Do not have an account?
<a class="js-animation-link" href="javascript:;" data-target="#signup" data-link-group="idForm"
data-animation-in="fadeIn">Signup
</a>
</p>
</div>
<!-- Divider -->
<div class="text-center u-divider-wrapper my-3">
<span class="u-divider u-divider--xs u-divider--text">OR</span>
</div>
<!-- End Divider -->
<!-- Signin Social Buttons -->
<div class="row mx-gutters-2 mb-4">
<div class="col-sm-6 mb-2 mb-sm-0">
<button type="button" class="btn btn-block btn-facebook text-nowrap">
<i class="fab fa-facebook-f mr-2"></i>
Signin with Facebook
</button>
</div>
<div class="col-sm-6">
<button type="button" class="btn btn-block btn-twitter">
<i class="fab fa-twitter mr-2"></i>
Signin with Twitter
</button>
</div>
</div>
<!-- End Signin Social Buttons -->
</div>
<!-- End Signin -->
<!-- Signup -->
<div id="signup" style="display: none; opacity: 0;" data-target-group="idForm">
<!-- Title -->
<header class="text-center mb-5">
<h2 class="h4 mb-0">Please sign up</h2>
<p>Fill out the form to get started.</p>
</header>
<!-- End Title -->
<!-- Input -->
<div class="js-form-message mb-3">
<div class="js-focus-state input-group form">
<div class="input-group-prepend form__prepend">
<span class="input-group-text form__text">
<i class="fa fa-user form__text-inner"></i>
</span>
</div>
<input type="email" class="form-control form__input" name="email" required placeholder="Email"
aria-label="Email" data-msg="Please enter a valid email address." data-error-class="u-has-error"
data-success-class="u-has-success">
</div>
</div>
<!-- End Input -->
<!-- Input -->
<div class="js-form-message mb-3">
<div class="js-focus-state input-group form">
<div class="input-group-prepend form__prepend">
<span class="input-group-text form__text">
<i class="fa fa-lock form__text-inner"></i>
</span>
</div>
<input type="password" class="form-control form__input" name="password" id="password" required
placeholder="Password" aria-label="Password" data-msg="Your password is invalid. Please try again."
data-error-class="u-has-error" data-success-class="u-has-success">
</div>
</div>
<!-- End Input -->
<!-- Input -->
<div class="js-form-message mb-3">
<div class="js-focus-state input-group form">
<div class="input-group-prepend form__prepend">
<span class="input-group-text form__text">
<i class="fa fa-key form__text-inner"></i>
</span>
</div>
<input type="password" class="form-control form__input" name="confirmPassword" required
placeholder="Confirm Password" aria-label="Confirm Password"
data-msg="Password does not match the confirm password." data-error-class="u-has-error"
data-success-class="u-has-success">
</div>
</div>
<!-- End Input -->
<div class="mb-3">
<button type="submit" class="btn btn-block btn-primary">Signup</button>
</div>
<div class="text-center mb-3">
<p class="text-muted">
Have an account?
<a class="js-animation-link" href="javascript:;" data-target="#signin" data-link-group="idForm"
data-animation-in="fadeIn">Conenxion Recruteur
</a>
</p>
</div>
<!-- Divider -->
<div class="text-center u-divider-wrapper my-3">
<span class="u-divider u-divider--xs u-divider--text">OR</span>
</div>
<!-- End Divider -->
<!-- Signup Social Buttons -->
<div class="row mx-gutters-2 mb-4">
<div class="col-sm-6 mb-2 mb-sm-0">
<button type="button" class="btn btn-block btn-facebook text-nowrap">
<i class="fab fa-facebook-f mr-2"></i>
Signup with Facebook
</button>
</div>
<div class="col-sm-6">
<button type="button" class="btn btn-block btn-twitter">
<i class="fab fa-twitter mr-2"></i>
Signup with Twitter
</button>
</div>
</div>
<!-- End Signup Social Buttons -->
</div>
<!-- End Signup -->
<!-- Forgot Password -->
<div id="forgotPassword" style="display: none; opacity: 0;" data-target-group="idForm">
<!-- Title -->
<header class="text-center mb-5">
<h2 class="h4 mb-0">Recover account</h2>
<p>Enter your email address and an email with instructions will be sent to you.</p>
</header>
<!-- End Title -->
<!-- Input -->
<div class="js-form-message mb-3">
<div class="js-focus-state input-group form">
<div class="input-group-prepend form__prepend">
<span class="input-group-text form__text">
<i class="fa fa-user form__text-inner"></i>
</span>
</div>
<input type="email" class="form-control form__input" name="email" required placeholder="Email"
aria-label="Email" data-msg="Please enter a valid email address." data-error-class="u-has-error"
data-success-class="u-has-success">
</div>
</div>
<!-- End Input -->
<div class="mb-3">
<button type="submit" class="btn btn-block btn-primary">Recover Account</button>
</div>
<div class="text-center mb-3">
<p class="text-muted">
Have an account?
<a class="js-animation-link" href="javascript:;" data-target="#signin" data-link-group="idForm"
data-animation-in="fadeIn">Contactez nous
</a>
</p>
</div>
<div class="text-center mb-3">
<p class="text-muted">
Have an account?
<a class="js-animation-link" href="javascript:;" data-target="#signin" data-link-group="idForm"
data-animation-in="fadeIn">Connexion Recruteur.
</a>
</p>
</div>
</div>
<!-- End Forgot Password -->
</form>
</div>
<!-- End Content -->
</div>
<!-- End Signup Modal Window -->
<!-- ========== END SECONDARY CONTENTS ========== -->
<!-- Go to Top -->
<a class="js-go-to u-go-to" href="javascript:;" data-position='{"bottom": 15, "right": 15 }' data-type="fixed"
data-offset-top="400" data-compensation="#header" data-show-effect="slideInUp" data-hide-effect="slideOutDown">
<i class="fa fa-arrow-up u-go-to__inner"></i>
</a>
<!-- End Go to Top -->
<!-- JS Global Compulsory -->
<script src="{{ asset('v2/vendor/jquery/dist/jquery.min.js') }}"></script>
<script src="{{ asset('v2/vendor/jquery-migrate/dist/jquery-migrate.min.js') }}"></script>
<script src="{{ asset('v2/vendor/popper.js/dist/umd/popper.min.js') }}"></script>
<script src="{{ asset('v2/vendor/bootstrap/bootstrap.min.js') }}"></script>
<!-- JS Implementing Plugins -->
<script src="{{ asset('v2/vendor/hs-megamenu/src/hs.megamenu.js') }}"></script>
<script src="{{ asset('v2/vendor/jquery-validation/dist/jquery.validate.min.js') }}"></script>
<script src="{{ asset('v2/vendor/malihu-custom-scrollbar-plugin/jquery.mCustomScrollbar.concat.min.js') }}"></script>
<script src="{{ asset('v2/vendor/custombox/dist/custombox.min.js') }}"></script>
<script src="{{ asset('v2/vendor/custombox/dist/custombox.legacy.min.js') }}"></script>
<script src="{{ asset('v2/vendor/typed.js/lib/typed.min.js') }}"></script>
<script src="{{ asset('v2/vendor/slick-carousel/slick/slick.js') }}"></script>
<script src="{{ asset('v2/vendor/cubeportfolio/js/jquery.cubeportfolio.min.js') }}"></script>
<script src="{{ asset('v2/vendor/fancybox/jquery.fancybox.min.js') }}"></script>
<!-- JS Space -->
<script src="{{ asset('v2/js/hs.core.js') }}"></script>
<script src="{{ asset('v2/js/components/hs.header.js') }}"></script>
<script src="{{ asset('v2/js/components/hs.unfold.js') }}"></script>
<script src="{{ asset('v2/js/components/hs.validation.js') }}"></script>
<script src="{{ asset('v2/js/helpers/hs.focus-state.js') }}"></script>
<script src="{{ asset('v2/js/components/hs.malihu-scrollbar.js') }}"></script>
<script src="{{ asset('v2/js/components/hs.fancybox.js') }}"></script>
<script src="{{ asset('v2/js/components/hs.modal-window.js') }}"></script>
<script src="{{ asset('v2/js/components/hs.show-animation.js') }}"></script>
<script src="{{ asset('v2/js/components/hs.slick-carousel.js') }}"></script>
<script src="{{ asset('v2/js/components/hs.cubeportfolio.js') }}"></script>
<script src="{{ asset('v2/js/components/hs.g-map.js') }}"></script>
<script src="{{ asset('v2/js/components/hs.go-to.js') }}"></script>
<!-- JS Plugins Init. -->
<script>
// initialization of google map
{# function initMap() {
$.HSCore.components.HSGMap.init('.js-g-map');
} #}
$(window).on('load', function () {
// initialization of HSMegaMenu component
$('.js-mega-menu').HSMegaMenu({
event: 'hover',
pageContainer: $('.container'),
breakpoint: 767,
hideTimeOut: 0
});
});
$(document).on('ready', function () {
// initialization of header
$.HSCore.components.HSHeader.init($('#header'));
// initialization of fancybox
$.HSCore.components.HSFancyBox.init('.js-fancybox');
// initialization of unfold component
$.HSCore.components.HSUnfold.init($('[data-unfold-target]'), {
afterOpen: function () {
if (!$('body').hasClass('IE11')) {
$(this).find('input[type="search"]').focus();
}
}
});
// initialization of form validation
$.HSCore.components.HSValidation.init('.js-validate', {
rules: {
confirmPassword: {
equalTo: '#password'
}
}
});
// initialization of forms
$.HSCore.helpers.HSFocusState.init();
// initialization of malihu scrollbar
$.HSCore.components.HSMalihuScrollBar.init($('.js-scrollbar'));
// initialization of autonomous popups
$.HSCore.components.HSModalWindow.init('[data-modal-target]', '.js-signup-modal', {
autonomous: true
});
// initialization of show animations
$.HSCore.components.HSShowAnimation.init('.js-animation-link');
// initialization of slick carousel
$.HSCore.components.HSSlickCarousel.init('.js-slick-carousel');
// initialization of text animation (typing)
var typed = new Typed(".u-text-animation.u-text-animation--typing", {
strings: ["Recrutez les candidats", "Boostez vos recrutements", "Valorisez vos collaborateurs"],
typeSpeed: 60,
loop: true,
backSpeed: 25,
backDelay: 3000
});
// initialization of cubeportfolio
$.HSCore.components.HSCubeportfolio.init('.cbp');
// initialization of go to
$.HSCore.components.HSGoTo.init('.js-go-to');
});
$(document).ready(function () {
$(window).scroll(function () { // check if scroll event happened
if ($(document).scrollTop() > 50) { // check if user scrolled more than 50 from top of the browser window
$("#logoAndNav").css("background-color",
"#000"); // if yes, then change the color of class "navbar-fixed-top" to white (#f8f8f8)
console.log("test");
} else {
$("#logoAndNav").css("background-color", "transparent"); // if not, change it back to transparent
console.log("test2");
}
});
});
</script>
{% endblock %}
{% block javascripts %}
{{ parent() }}
<script src="https://player.vimeo.com/api/player.js"></script>
{% endblock %}
@@ -0,0 +1,61 @@
{% for a in ads if a.isPrivate != true %}
<div class="col s12">
<div class="card z-depth-3">
<div class="card-image">
{% if a.video %}
{% if a.video.thumbnails.0.sizes is defined %}
<a href="{{ path('ad_show',{'alias': a.alias }) }}" title="{{ a.title }}">
<img src="{{ a.video.thumbnails.0.sizes.4.link }}" alt="{{ a.company.brandName }}"/>
<span class="playerbtn"></span>
</a>
{% endif %}
{% endif %}
{% if a.isPromoted %}
<div class="isPromoted"><img src="{{asset('/img/offre-pourvue-droite.png')}}" alt="promoted"></div>
{% endif %}
</div>
<div class="card-content-wrapper">
<div class="card-content card-content-company">
<div class="row company-infos row-noMargin">
<div class="col-infos">
<p class="item-list-name color-blue1">
<a href="{{ path('company_show',{'alias': a.company.alias }) }}" title="{{ a.company.brandName }}">
{{ a.company.brandName }}
</a>
</p>
{% if a.location is iterable %}
{% if a.location.gmap_address %}
<p class="item-list-city">{{ a.location.gmap_address.address_components.0.long_name }}</p>
{% endif %}
{% endif %}
</div>
<div class="col-logo">
{% if a.company.webPath %}
<img class="responsive-img" src="{{ a.company.webPath | imagine_filter('profile_thumb') }}"/>
{% endif %}
</div>
</div>
</div>
<div class="card-content card-content-ad">
<a class="link-job left-align truncate" href="{{ path('ad_show',{'alias': a.alias }) }}" title="{{ a.title }}">{{ a.title }}</a>
</div>
<div class="card-action">
<a class="btn-tags" href="#">Les mots clés<i class="fa fa-chevron-up right" aria-hidden="true"></i></a>
<span class="clearfix"></span>
<div class="keywords">
{% if a.publicTag %}
{% for tag in a.publicTag %}
<div class="chip">
<a href="{{ path('ad_search_result',{'tag':tag }) }}">{{ tag }}</a>
</div>
{% endfor %}
{% endif %}
</div>
</div>
</div>
<div class="borderList"></div>
</div>
</div>
{% endfor %}
@@ -0,0 +1,69 @@
{% for a in ads if a.isPrivate != true %}
<div id="adRow" class="row item-list-bis z-depth-2 row-noMargin">
<div class="col s12 m4 col-noPadding ad-picture">
<a href="{{ path('ad_show',{'alias': a.alias }) }}" title="{{ a.title }}" class="item-list-media">
{% if a.video %}
{% if a.video.thumbnails.0.sizes is defined %}
<img class="thumbnail_list" src="{{ a.video.thumbnails.0.sizes.4.link }}"
alt="{{ a.company.brandName }}"/>
{% endif %}
<span class="playerbtn"></span>
{% endif %}
</a>
{% if a.isPromoted %}
<div class="isPromoted">
OFFRE POURVUE
</div>
{% endif %}
</div>
<div class="col s12 m8 col-noPadding">
<div class="row row-infos row-noMargin">
<div class="col s4 m4 l5 company-infos col-noPadding">
<h2 class="no-margin-top">
<a href="{{ path('ad_show',{'alias': a.alias }) }}"
title="{{ a.title }}" class="hover-blue1">{{ a.title }}</a>
</h2>
{% if a.extra.contract_type is defined %}
<span>{{ a.extra.contract_type }}</span>
{% endif %}
</div>
<div class="col s4 m3 l3 col-noPadding col-logo">
{% if (a.company.logo is defined) and (a.company.webPath is not null) %}
<a href="{{ path('company_show',{'alias':a.company.alias}) }}">
<img src="{{ a.company.webPath | imagine_filter('profile_thumb') }}"/>
</a>
{% endif %}
</div>
<div class="hide-on-small-only col s4 m5 l4 col-noPadding company-infos m-l-30">
<p class="item-list-website">
<a href="{{ path('company_show',{'alias': a.company.alias }) }}" class="hover-blue2">
{{ a.company.brandName }}
</a>
<br/>
{% if a.location is iterable %}
<span>{{ a.location.gmap_address.address_components.0.long_name }}</span>
{% endif %}
</p>
</div>
</div>
<div class="row row-tags row-noMargin">
<div class="col s11 col-noPadding" style="position:relative;">
<div class="frame" id="basic">
<ul class="slidee">{% for tag in a.publicTag %}
<li class="chip">
<a href="{{ path('ad_search_result',{'tag':tag }) }}" class="hover-blue2">{{ tag }}</a>
</li>{% endfor %}</ul>
</div>
<div class="controls center">
<a class="prev"><i class="fa fa-arrow-circle-left" aria-hidden="true"></i></a>
<a class="next"><i class="fa fa-arrow-circle-right" aria-hidden="true"></i></a>
</div>
</div>
</div>
</div>
<div class="borderList"></div>
<div class="clearfix"></div>
</div>
{% endfor %}
@@ -0,0 +1,80 @@
{% extends 'base.html.twig' %}
{% block title %}Découvrez toutes les offres d'emploi en vidéo sur Talents Tube{% endblock %}
{% block description %}Découvrez toutes les offres d'emploi en vidéo dans votre région sur Talents Tube. Postulez rapidement en vidéo et trouvez votre futur job !{% endblock %}
{% block ogtc %}
{#Twitter Card data pour les données enrichies sur Twitter#}
<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="@TalentsTube">
<meta name="twitter:title" content="Découvrez toutes les offres d'emploi en vidéo sur Talents Tube">
<meta name="twitter:description" content="Découvrez toutes les offres d'emploi en vidéo dans votre région sur Talents Tube. Postulez rapidement en vidéo et trouvez votre futur job !">
<meta name="twitter:image" content="{{ absolute_url(asset('img/mail/logo-talents-tube.png')) }}">
{#Open Graph data pour le partage sur les réseaux sociaux (ex Facebook..)#}
<meta property="og:title" content="Découvrez toutes les offres d'emploi en vidéo sur Talents Tube" />
<meta property="og:type" content="article" />
<meta property="og:image" content="{{ absolute_url(asset('img/mail/logo-talents-tube.png')) }}" />
<meta property="og:description" content="Découvrez toutes les offres d'emploi en vidéo dans votre région sur Talents Tube. Postulez rapidement en vidéo et trouvez votre futur job !" />
<meta property="og:site_name" content="Talents Tube" />
<meta property="og:url" content="{{ url(app.request.attributes.get('_route'), app.request.attributes.get('_route_params')) }}" />
{% endblock %}
{% block content %}
{{ render(controller('AppBundle:Ad:adSearchRender',{'type': 'lite' })) }}
<div class="fluid-container bg-grey-3 contentPage">
<div id="searchResultWrapper" class="container">
<div class="row">
<div class="col s12 center-align">
<h1 class="alttitle">Les offres demploi en vidéo</h1>
</div>
</div>
<div class="row m-b-0 p-b-30">
<div class="col s12 m12">
<div id="header-resultats">
{% if isPromotedAds %}
<div><span class="color-blue2">{{ ads|length }}</span> offres d'emploi pourvues</div>
<div><span><a href="{{ path('ad_search_result') }}">Voir les offres d'emploi en cours</a></span></div>
{% else %}
<div><span class="color-blue2">{{ ads|length }}</span> offres d'emploi en cours</div>
<div><span><a href="{{ path('ad_search_result', {'promoted': true }) }}">Voir les offres d'emploi pourvues</a></span></div>
{% endif %}
</div>
<div id="liste-resultats">
{% if ads|length > 0 and noResults == false %}
{% include 'default/ad_listing.html.twig' with {'ads':ads} %}
{% else %}
<h2 class="center-align">Il n'y a pas de résultats directs à votre recherche</h2>
<h4 class="center-align">Mais vous pourriez être intéressé(e) par</h4>
<br/>
{% include 'default/ad_listing.html.twig' with {'ads':ads} %}
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block javascripts %}
{{ parent() }}
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDYV8IJGtIoWLfXJQQvIuDQ88n2aEuRgpg&libraries=places"></script>
<script type="text/javascript">
$(document).ready(function () {
var input = /** @type {!HTMLInputElement} */(document.getElementById('ad_search_location_gmap'));
var autocomplete = new google.maps.places.Autocomplete(input);
autocomplete.addListener('place_changed', onPlaceChanged);
function onPlaceChanged() {
var place = autocomplete.getPlace();
var gmap_address = {'gmap_address': place}
if (place.geometry) {
$("#ad_search_location").val(JSON.stringify(gmap_address));
}
}
});
</script>
{% endblock %}
@@ -0,0 +1,218 @@
{% extends 'base.html.twig' %}
{% block title %}{{ ad.htmlTitle|raw }}{% endblock %}
{% block description %}{{ ad.htmlDescription|raw }}{% endblock %}
{% block ogtc %}
{#Twitter Card data pour les données enrichies sur Twitter#}
<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="@TalentsTube">
<meta name="twitter:title" content="{{ ad.htmlTitle|raw }}">
<meta name="twitter:description" content="{{ ad.htmlDescription|raw }}">
<meta name="twitter:image"
content="{% if ad.video %}{% if ad.video.thumbnails.0.sizes is defined %}{{ ad.video.thumbnails.0.sizes.4.link }}{% endif %}{% endif %}
">
{#Open Graph data pour le partage sur les réseaux sociaux (ex Facebook..)#}
<meta property="og:title" content="{{ ad.htmlTitle|raw }}"/>
<meta property="og:type" content="article"/>
<meta property="og:url" content="{{ app.request.uri }}"/>
<meta property="og:image"
content="{% if ad.video %}{% if ad.video.thumbnails.0.sizes is defined %}{{ ad.video.thumbnails.0.sizes.4.link }}{% endif %}{% endif %}"/>
<meta property="og:description" content="{{ ad.htmlDescription|raw }}"/>
<meta property="og:site_name" content="Talents Tube"/>
{% endblock %}
{% block content %}
{% include 'default/flash_message.html.twig' %}
<div class="fluid-container bg-grey-3 button-plus">
<div id="ad_show" class="container contentWrapper contentPage">
<div class="row">
<div class="col s12 m12 l4 xl3 hide-on-med-and-down" id="sidebar">
{% include 'default/ad_sidebar.html.twig' with {'ad': ad, 'showBrand': true} %}
</div>
<div class="col s12 m12 l8 xl9">
{% if ad.video and ad.status != "CLOSED" %}
<div class="row m-b-0" id="adVideo">
{#{% if ad.id == 38 %}
<img class="responsive-img" src="{{asset('/img/GROUPE-ROCHER-TT.jpg')}}">
{% else %}#}
<div class="embed-responsive embed-responsive-16by9">
<div class="col s12">
<iframe src="https://player.vimeo.com/video/{{ ad.video.cdnUrl|replace({ "/videos/": ""}) }}?texttrack=fr"
width="100%" height="640" frameborder="0" webkitallowfullscreen mozallowfullscreen
allowfullscreen></iframe>
</div>
</div>
{#{% endif %}#}
{% if ad.isPromoted %}
<div class="isPromoted">
OFFRE POURVUE
</div>
{% endif %}
{% if ad.id == 53 %}
<div class="isPromoted">
Traitement des candidatures vidéos
</div>
{% endif %}
</div>
{% endif %}
<div class="row bg-bordered">
<div class="row row-title-ad">
<div class="col s6 col-title-ad">
<h1>{%- spaceless -%}{{ ad.title}}{%- endspaceless -%}</h1>
</div>
<div class="col s6 col-type-ad">
<h2>
{% if ad.extra.contract_type is defined %}
<i class="fa fa-suitcase" aria-hidden="true"></i>&nbsp;{{ ad.extra.contract_type }}
{% endif %}
{% if ad.location is iterable %}
{% if ad.location.gmap_address %}
<i class="fa fa-map-marker" aria-hidden="true"></i>&nbsp;{{ ad.location.gmap_address.address_components.0.long_name }}
{% endif %}
{% endif %}
</h2>
</div>
</div>
<div class="col s12">
{% for tag in ad.publicTag %}
<p class="chip"><a href="{{ path('ad_search_result',{'tag':tag }) }}" class="hover-blue2">{{ tag }}</a></p>
{% endfor %}
<div class="item-detail-description">
<h3 class="blue-text">Détails de l'offre d'emploi</h3>
<p>{{ ad.description|nl2br }}</p>
</div>
<h3 class="blue-text">Informations complémentaires</h3>
<p class="item-detail-reference">Référence : <span>{{ ad.reference }}</span></p>
<p class="item-detail-date">Publié le : <span>{{ ad.publishedAt|date('d/m/Y') }}</span></p>
</div>
<div class="col s12 center-align">
{% if ad.status == "CLOSED" %}
<div class="card-panel orange lighten-1 whiteColor">
{{ 'Offre cloturée'|trans }}
</div>
{% else %}
{% if is_granted('ROLE_TALENT') and alreadyAnswered == TRUE %}
<div class="card-panel green lighten-1 whiteColor">
{{ 'ad.talent.isAnswer.label'|trans }}
</div>
{% elseif not is_granted('ROLE_COMPANY') %}
{% if not ad.isPromoted %}
{% if ad.id != 53 %}
<p class="item-detail-reply">
<a title="postuler-bottom" href="{{ path('talent_answer_create',{'id': ad.getId()}) }}"
class="btn btn-default">
Postuler
</a>
</p>
{% endif %}
{% endif %}
{% endif %}
{% endif %}
</div>
</div>
{% if ad.isPromoted %}
<div class="row bg-bordered row-promoted">
<div class="col s12 center-align">
<h3>Vous souhaitez rejoindre <span class="color-blue1">{{ ad.company.brandname }}</span> ?</h3>
<a href="{{ path('talent_spontaneous_application_create',{'id': ad.company.getId()}) }}"
class="btn btn-default">
Candidature spontanée
</a>
</div>
</div>
{% endif %}
<div class="col s12 hide-on-large-only m-b-50">
{% include 'default/ad_sidebar.html.twig' with {'ad': ad, 'showBrand': true} %}
</div>
</div>
<div class="row">
{% if companyAds|length > 0 %}
<div class="col s12">
<h2>Autres offres demploi pour {{ ad.company.brandname }}</h2>
<div id="liste-resultats">
{% include 'default/ad_listing.html.twig' with {'ads':companyAds} %}
</div>
</div>
{% endif %}
</div>
</div>
</div>
</div>
{% if ad.territories|length %}
{% include 'ad/carrousel_territory.html.twig' with {'territories': ad.territories } %}
{% elseif ad.company.territories|length %}
{% include 'ad/carrousel_territory.html.twig' with {'territories': ad.company.territories } %}
{% endif %}
{% set popup_answer_send = app.session.flashbag.get('popup_answer_send') %}
{% set popup_answer_already_send = app.session.flashbag.get('popup_answer_already_send') %}
{% if popup_answer_send is not empty %}
{% if popup_answer_send[0] == true %}
<div id="modal-answer" class="modal">
<div class="modal-content">
<div class="row">
<div class="col s12">
<div class="col-content p-30">
{% if popup_answer_already_send is not empty and popup_answer_already_send[0] == true %}
<h3 class="color-blue1 center-align">Candidature pour {{ ad.company.brandname }} !</h3>
<div class="col offset-s2 s8 center-align">
<p>Vous avez déjà répondu à cette annonce.</p>
<a href="{{ path('talent_dashboard') }}" class="btn btn-default m-t-20">Accéder à mon profil</a>
<br /><br />
<a class="text modal-action modal-close">Fermer</a>
</div>
{% else %}
<h3 class="color-blue1 center-align">Votre candidature a bien été envoyée à {{ ad.company.brandname }} !</h3>
<div class="col offset-s2 s8 center-align">
<div class="embed-responsive embed-responsive-16by9">
<div class="col s12">
<iframe src="https://player.vimeo.com/video/249822507"
width="100%" height="640" frameborder="0"></iframe>
</div>
</div>
<a href="{{ path('talent_dashboard') }}" class="btn btn-default m-t-20">Accéder à mon profil</a>
<br /><br />
<a class="text modal-action modal-close">Fermer</a>
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% endif %}
{% endif %}
{% endblock %}
{% block javascripts %}
{{ parent() }}
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDYV8IJGtIoWLfXJQQvIuDQ88n2aEuRgpg&libraries=places"></script>
<script type="text/javascript">
$(document).ready(function(){
//asking for push
EdeclicLib = window.EdeclicLib || {};
EdeclicLib.delayedAsk();
//
$('.tooltipped').tooltip();
$.get( "{{ path('ad_ajaxRecStat',{'id': ad.id }) }}", function( data ) {});
if ($('#modal-answer').length > 0) {
$('#modal-answer').modal({
dismissible: false,
ready: function(modal, trigger) {}
});
$('#modal-answer').modal('open');
}
});
</script>
{% endblock %}
{% block stylesheets %}
<script type="application/ld+json">
{{- ad.structuredData|raw -}}
</script>
<script type="text/javascript" src="//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-5a095d2dd3cf90df"></script>
{% endblock %}
@@ -0,0 +1,75 @@
<div class="profil-company center-align">
{% set company = ad.company %}
<a href="{{ path('company_show',{'alias': ad.company.alias }) }}" title="{{ ad.company.brandName }}" class="profil-picture logo-picture">
{% if company.logo %}
<img class="responsive-img" src="{{ company.webPath | imagine_filter('profile_thumb') }}"
alt="{{ company.brandname }}"/>
{% else %}
<div class="circle-letters square-letters font-2">{{ company.brandname|first|upper }}</div>
{% endif %}
</a>
{% if showBrand is defined %}
{% if company.presentationVideo %}
<div class="brandImage">
<a href="{{ path('company_show',{'alias': ad.company.alias }) }}" title="{{ ad.company.brandName }}">
<img class="" src="{{ company.presentationVideo.thumbnails.0.sizes.4.link }}">
<span class="filter"></span>
<span class="playerbtn"></span>
</a>
</div>
{% endif %}
{% endif %}
<a href="{{ path('company_show',{'alias': ad.company.alias }) }}" title="{{ ad.company.brandName }}" class="btn btn-default btn-small-grey">
Découvrir l'employeur
</a>
<p class="profil-name">
<a href="{{ path('company_show',{'alias': company.alias }) }}" title="{{ company.brandName }}">
<b>{{ company.brandname }}</b>
</a>
</p>
{% if company.addresses.billing is defined %}
<p class="profil-city">{{ company.addresses.billing.city }}
- {{ company.addresses.billing.country|country }}</p>
{% endif %}
</div>
{#<div class="col s12 profil-links">
{% if company.website %}
<a target="_blank" href="{{ company.website }}" class="td-none">
<span class="fa-stack fa-lg">
<i class="fa fa-circle fa-stack-2x z-depth-2"></i>
<i class="fa fa-link fa-stack-1x fa-inverse"></i>
</span>
</a>
{% endif %}
</div>#}
<div class="col s12 center-align">
<div class="divider"></div>
<br />
{% if ad.status == "CLOSED" %}
<div class="card-panel orange lighten-1 whiteColor">
{{ 'Offre cloturée'|trans }}
</div>
{% else %}
{% if is_granted('ROLE_TALENT') and alreadyAnswered == TRUE %}
<div class="card-panel green lighten-1 whiteColor">
{{ 'ad.talent.isAnswer.label'|trans }}
</div>
{% elseif not is_granted('ROLE_COMPANY') %}
{% if not ad.isPromoted %}
{% if ad.id != 53 %}
<p class="item-detail-reply">
<a title="postuler-side" href="{{ path('talent_answer_create',{'id': ad.getId()}) }}"
class="btn btn-default">
Postuler
</a>
</p>
{% endif %}
{% else %}
<div class="item-detail-ispromoted">
Offre pourvue
</div>
{% endif %}
{% endif %}
{% endif %}
</div>
@@ -0,0 +1,7 @@
{% for type, flash_messages in app.session.flashBag.all %}
{% for flash_message in flash_messages %}
<div class="flash-{{ type }}">
{{ flash_message }}
</div>
{% endfor %}
{% endfor %}
@@ -0,0 +1,31 @@
{% if not app.user or is_granted('ROLE_TALENT_TMP')%}
<div class="header-link header-link-signin right-align">
{% if app.request.get('_route') == "fos_user_security_login" %}
{% set href = "" %}
{% else %}
{% set href = "#modal_login" %}
{% endif %}
<a class="btn button-round-small" href="{{ href }}">
<i class="fa fa-power-off" aria-hidden="true"></i>
<span>Connexion</span>
</a>
</div>
{% else %}
<div class="header-link header-link-signin right-align">
{% if is_granted('ROLE_TALENT') %}
{% set pathDash = path('talent_dashboard') %}
{% elseif is_granted('ROLE_COMPANY') %}
{% set pathDash = path('company_dashboard') %}
{% elseif is_granted('ROLE_TERRITORY') %}
{% set pathDash = path('territory_dashboard') %}
{% elseif is_granted('ROLE_ADMIN') %}
{% set pathDash = path('admin_dashboard') %}
{% else %}
{% set pathDash = path('talent_dashboard') %}
{% endif %}
<a class="btn button-round-small" href="{{ pathDash }}">
<i class="material-icons">perm_identity</i>
<span>Mon compte</span>
</a>
</div>
{% endif %}
@@ -0,0 +1,60 @@
{% for company in companies if company.isPrivate != true %}
<div class="col s12">
<div class="card z-depth-3 card-company">
<div class="card-content card-content-company">
<div class="row row-noMargin">
<div class="col s4 col-logo">
{% if company.logo is not null %}
<img class="responsive-img" src="{{ company.webPath | imagine_filter('profile_thumb') }}"/>
{% endif %}
</div>
<div class="col s8 col-infos">
<p class="item-list-name color-blue1">
<a href="{{ path('company_show',{'alias': company.alias }) }}"
title="{{ company.brandName }}">
{{ company.brandName }}
</a>
</p>
{% if company.addresses %}
<span class="truncate">{{ company.addresses.billing.city }}</span>
{% endif %}
</div>
</div>
</div>
<div class="card-image">
{% if company.presentationVideo is defined %}
{% if company.presentationVideo.thumbnails.0.sizes is defined %}
<a href="{{ path('company_show',{'alias': company.alias }) }}" title="{{ company.brandName }}">
<img src="{{ company.presentationVideo.thumbnails.0.sizes.4.link }}"
alt="{{ company.brandName }}"/>
<span class="playerbtn"></span>
</a>
{% endif %}
{% endif %}
</div>
<div class="card-content-wrapper">
<div class="card-content">
<div class="row">
<div class="col s12 card-infos-company">
<div class="chip center-align">
<a class="td-none color-grey3" href="{{ path('company_show',{'alias': company.alias, '_fragment':'offers' }) }}">
{% set nbAds = company.getPublishedAds|length %}
{% if nbAds > 1 %}
<strong>{{company.getPublishedAds|length}} offres d'emploi en cours</strong>
{% else %}
<strong>{{company.getPublishedAds|length}} offre d'emploi en cours</strong>
{% endif %}
</a>
</div>
</div>
</div>
</div>
</div>
<div class="borderList"></div>
</div>
</div>
{% endfor %}
@@ -0,0 +1,48 @@
{% extends 'base.html.twig' %}
{% block title %}Les entreprises qui recrutent en vidéo | TalentsTube{% endblock %}
{% block description %}Découvrez les entreprises qui recrutent en vidéo, elles dévoilent leurs marques employeur et leurs offres d'emploi en vidéo. Postulez rapidement à l'offre qui vous convient.{% endblock %}
{% block ogtc %}
{#Twitter Card data pour les données enrichies sur Twitter#}
<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="@TalentsTube">
<meta name="twitter:title" content="Les entreprises qui recrutent en vidéo | TalentsTube">
<meta name="twitter:description"
content="Découvrez les entreprises qui recrutent en vidéo, elles dévoilent leurs marques employeur et leurs offres d'emploi en vidéo. Postulez rapidement à l'offre qui vous convient.">
<meta name="twitter:image" content="{{ absolute_url(asset('img/mail/logo-talents-tube.png')) }}">
{#Open Graph data pour le partage sur les réseaux sociaux (ex Facebook..)#}
<meta property="og:title" content="Les entreprises qui recrutent en vidéo | TalentsTube"/>
<meta property="og:type" content="article"/>
<meta property="og:image" content="{{ absolute_url(asset('img/mail/logo-talents-tube.png')) }}"/>
<meta property="og:description"
content="Découvrez les entreprises qui recrutent en vidéo, elles dévoilent leurs marques employeur et leurs offres d'emploi en vidéo. Postulez rapidement à l'offre qui vous convient."/>
<meta property="og:site_name" content="Talents Tube"/>
<meta property="og:url"
content="{{ url(app.request.attributes.get('_route'), app.request.attributes.get('_route_params')) }}"/>
{% endblock %}
{% block content %}
{{ render(controller('AppBundle:Ad:adSearchRender',{'type': 'lite' })) }}
<div class="fluid-container bg-grey-3 contentPage">
<div id="searchResultWrapper" class="container">
<div class="row">
<div class="col s12 center-align">
<h1 class="alttitle">Les entreprises de talents</h1>
</div>
</div>
<div class="row m-b-0 p-b-30">
<div class="col s12 m12">
<div id="liste-resultats">
{% include 'default/company_listing.html.twig' with {'companies':companies} %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}
@@ -0,0 +1,81 @@
{% for c in companies if c.isPrivate != true %}
{% if (c.presentationVideo is not null or c.getPublishedAds|length > 0 ) %}
<div class="row item-list-bis z-depth-2 row-noMargin">
<div class="col s12 m2 ad-picture col-logo-lg">
<a href="{{ path('company_show',{'alias': c.alias }) }}"
title="{{ c.brandname }}">
{% if c.logo is not null %}
<img src="{{ c.webPath | imagine_filter('profile_thumb') }}"/>
{% endif %}
</a>
</div>
<div class="col s12 m6 col-noPadding">
<div class="row row-infos row-noMargin">
<div class="col s4 m5 l4 col-noPadding company-infos m-l-30">
<div class="item-list-website">
<h2>
<a href="{{ path('company_show',{'alias': c.alias }) }}"
class="hover-blue2">
<b>{{ c.brandName }}</b>
</a>
</h2>
<br/>
{{ c.init }}
{% if c.city != null %}
{{ c.city }}
{% endif %}
</div>
</div>
</div>
<div class="row row-tags row-noMargin">
<div class="col s11 col-noPadding" style="position:relative;">
<div class="chip center-align">
{% set nbAds = c.getPublishedAds|length %}
{% set fragment = "" %}
{% if nbAds > 0 %}
{% set fragment = "offers" %}
{% endif %}
<a class="td-none color-grey3"
href="{{ path('company_show',{'alias': c.alias, '_fragment': fragment }) }}">
{% set nbAds = c.getPublishedAds|length %}
{% if nbAds > 1 %}
<strong>{{ c.getPublishedAds|length }} offres d'emploi en
cours</strong>
{% elseif nbAds == 1 %}
<strong>{{ c.getPublishedAds|length }} offre d'emploi en
cours</strong>
{% else %}
<strong>candidature spontanée</strong>
{% endif %}
</a>
</div>
</div>
</div>
</div>
<div class="col s12 m4 col-noPadding ad-picture">
<a href="{{ path('company_show',{'alias': c.alias }) }}"
title="{{ c.brandname }}"
class="item-list-media">
{% if c.presentationVideo %}
{% if c.presentationVideo.thumbnails.0.sizes is defined %}
<img class="thumbnail_list"
src="{{ c.presentationVideo.thumbnails.0.sizes.4.link }}"
alt="{{ c.brandName }}"/>
{% endif %}
<span class="playerbtn"></span>
{% else %}
<img class="thumbnail_list"
src="{{ asset('/img/default_picture_company.svg') }}"
alt="{{ c.brandName }}"/>
{% endif %}
</a>
</div>
<div class="borderList"></div>
<div class="clearfix"></div>
</div>
{% endif %}
{% endfor %}
@@ -0,0 +1,15 @@
{% if destination_login is defined %}
{% set destination = destination_login %}
{% else %}
{% set destination = path('redirect_dashboard') %}
{% endif %}
<a class="btn btn-default btn-facebook z-depth-2" href="{{ url("hwi_oauth_service_redirect", {service: "facebook"}) }}?_destination={{ destination }}">Connexion avec Facebook</a>
{# <a class="btn btn-default btn-linkedin z-depth-2" href="{{ url("hwi_oauth_service_redirect", {service: "linkedin"}) }}?_destination={{ destination }}">Connexion avec Linkedin</a> #}
<div class="row">
<div class="col s12">
<div class="separator-with-label">
<hr>
<label><span>ou</span></label>
</div>
</div>
</div>
@@ -0,0 +1,11 @@
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function(event) {
{% for flashMessage in app.session.flashbag.get('notice') %}
var message = "{{ flashMessage }}";
{% endfor %}
if(typeof(message) !== "undefined"){
var $toastContent = $('<span>'+message+'</span>');
Materialize.toast($toastContent, 5000);
}
});
</script>
@@ -0,0 +1,86 @@
<footer class="page-footer">
<div class="container">
<div class="row footer-info">
<div class="col xl2 l2 m6 s12 col-footer-logo">
<img src="{{ asset('/img/logo-mini-white.svg') }}" alt="Talents Tube 1er job board 100% vidéo">
</div>
<div class="col xl3 l3 m6 s6">
<h5 class="white-text">Talents Tube</h5>
<ul>
<li>
<a class="white-text" href="{{ path('homepage') }}">Accueil</a>
</li>
<li>
<a class="white-text" href="{{ path('ad_search_result') }}" title="Offres d'emploi vidéos">Nos offres d'emploi</a>
</li>
<li>
<a class="white-text" href="{{ path('company_list') }}" title="Listes entreprises">Nos entreprises</a>
</li>
<li>
<a class="white-text" href="{{ path('territory_list') }}" title="Listes des territoires">Nos territoires</a>
</li>
<li>
<a class="white-text" href="https://blog.talentstube.com/contact.html" title="Talents Tube ">Contact</a>
</li>
</ul>
</div>
<div class="col xl4 l4 m6 s6">
<h5 class="white-text">Informations</h5>
<ul>
<li>
<a class="white-text" href="{{ path('service_legals') }}">Mentions légales</a>
</li>
<li>
<a class="white-text" href="{{ path('service_cgu') }}">Conditions générales d'utilisation</a>
</li>
<li>
<a class="white-text" href="{{ path('page_Confidentialite') }}">Politique de confidentialité et protection des données</a>
</li>
</ul>
</div>
<div class="col xl3 l3 m6 s12 left-align">
<h5 class="white-text">Suivez-nous !</h5>
<p class="footer-socials">
<a class="white-text td-none" href="https://www.facebook.com/TalentsTuber/" title="Facebook" target="_blank">
<i class="fa fa-facebook" aria-hidden="true"></i>
</a>
<a class="white-text td-none" href="https://twitter.com/TalentsTuber" title="Twitter" target="_blank">
<i class="fa fa-twitter" aria-hidden="true"></i>
</a>
<a class="white-text td-none" href="https://www.youtube.com/channel/UCRNqiJCLAorO0aCzNQu-8ww" title="Youtube" target="_blank">
<i class="fa fa-youtube" aria-hidden="true"></i>
</a>
<a class="white-text td-none" href="https://www.linkedin.com/company/talentstube" title="Linkedin" target="_blank">
<i class="fa fa-linkedin-square" aria-hidden="true"></i>
</a>
</p>
<h5 class="white-text">Contactez-nous !</h5>
<a class="white-text" href="mailto:&#098;&#111;&#110;&#106;&#111;&#117;&#114;&#064;&#116;&#097;&#108;&#101;&#110;&#116;&#115;&#116;&#117;&#098;&#101;&#046;&#099;&#111;&#109;">Par mail</a>
<p class="white-text">02 30 05 06 31</p>
<p class="footer-newsletter">
<a class="btn-large btn-round" href="#" title="Newsletter" data-token="ecea5416671e97e3abfa8195848a9140" onclick="mjOpenPopin(event, this)">
<i class="fa fa-envelope-open-o left" aria-hidden="true"></i>
Newsletter</a>
<data data-token="ecea5416671e97e3abfa8195848a9140" class="mj-w-data" data-apikey="2jWA" data-w-id="31E" data-lang="fr_FR" data-base="https://app.mailjet.com" data-width="640" data-height="420" data-statics="statics"></data>
</p>
</div>
</div>
<div class="row footer-more-links">
<div class="col s12 center-align">
<p class="text-center white-text">Entreprise soutenue par</p>
<a href="https://www.bretagne.bzh/"><img src="{{ asset('img/RB_monochrome_blanc.svg')}}" alt="Region Bretagne"></a><br>
</div>
<div class="col s12 center-align m-t-30">
<a class="text-center white-text" href="https://www.e-declic.com" target="_blank" title="Agence Web">&copy;&nbsp;2018 Talents Tube</a>
</div>
</div>
</div>
</footer>
{# Modal Login#}
{% if app.request.get('_route') != "fos_user_security_login" %}
<div id="modal_login" class="modal ">
<div class="modal-content">
{{ render(controller('AppBundle:SecurityModal:loginModal')) }}
</div>
</div>
{% endif %}
@@ -0,0 +1,161 @@
<!-- Skippy -->
<a id="skippy" class="sr-only sr-only-focusable u-skippy" href="#content">
<div class="container">
<span class="u-skiplink-text">Skip to main content</span>
</div>
</a>
<!-- End Skippy -->
<!-- ========== HEADER ========== -->
<header id="header" class="u-header u-header--modern u-header--bordered u-header--bg-transparent u-header--white-nav-links u-header--sticky-top-lg">
<div class="u-header__section">
<div id="logoAndNav" class="container-fluid">
<!-- Nav -->
<nav class="js-mega-menu navbar navbar-expand-lg u-header__navbar">
<!-- Logo -->
<div class="u-header__navbar-brand-wrapper">
<a class="navbar-brand u-header__navbar-brand" href="#" aria-label="TT">
<img class="u-header__navbar-brand-default" src="{{ asset('v2/svg/logos/talents-tube-logo.svg') }}" alt="Logo">
<img class="u-header__navbar-brand-mobile" src="{{ asset('v2/svg/logos/talentstube-logo-mobile.svg') }}" alt="Logo">
<img class="u-header__navbar-brand-on-scroll" src="{{ asset('v2/svg/logos/talents-tube-logo.svg') }}" alt="Logo">
</a>
</div>
<!-- Responsive Toggle Button -->
<button type="button" class="navbar-toggler btn u-hamburger u-header__hamburger"
aria-label="Toggle navigation"
aria-expanded="false"
aria-controls="navBar"
data-toggle="collapse"
data-target="#navBar">
<span class="d-none d-sm-inline-block">Menu</span>
<span id="hamburgerTrigger" class="u-hamburger__box ml-3">
<span class="u-hamburger__inner"></span>
</span>
</button>
<!-- End Responsive Toggle Button -->
<!-- Navigation -->
<div id="navBar" class="collapse navbar-collapse u-header__navbar-collapse py-0">
<ul class="navbar-nav u-header__navbar-nav">
<!-- Home -->
<li class="nav-item hs-has-sub-menu u-header__nav-item"
data-event="hover"
data-animation-in="fadeInUp"
data-animation-out="fadeOut">
<a id="homeMegaMenu" class="nav-link u-header__nav-link" href="javascript:;"
aria-haspopup="true"
aria-expanded="false"
aria-labelledby="homeSubMenu">
Offres d'emploi vidéo
<i class="fa fa-angle-down u-header__nav-link-icon"></i>
</a>
</li>
<!-- End Home -->
<!-- Pages -->
<li class="nav-item hs-has-mega-menu u-header__nav-item"
data-event="hover"
data-animation-in="fadeInUp"
data-animation-out="fadeOut"
data-position="right">
<a id="PagesMegaMenu" class="nav-link u-header__nav-link" href="javascript:;"
aria-haspopup="true"
aria-expanded="false">
Marque employeur Vidéo
<i class="fa fa-angle-down u-header__nav-link-icon"></i>
</a>
</li>
<!-- End Pages -->
<!-- Works -->
<li class="nav-item hs-has-sub-menu u-header__nav-item"
data-event="hover"
data-animation-in="fadeInUp"
data-animation-out="fadeOut">
<a id="worksMegaMenu" class="nav-link u-header__nav-link" href="javascript:;"
aria-haspopup="true"
aria-expanded="false"
aria-labelledby="worksSubMenu">
Candidatures vidéo
<i class="fa fa-angle-down u-header__nav-link-icon"></i>
</a>
</li>
<!-- End Works -->
<!-- Blog -->
<li class="nav-item hs-has-sub-menu u-header__nav-item"
data-event="hover"
data-animation-in="fadeInUp"
data-animation-out="fadeOut">
<a id="blogMegaMenu" class="nav-link u-header__nav-link" href="javascript:;"
aria-haspopup="true"
aria-expanded="false"
aria-labelledby="blogSubMenu">
Blog
<i class="fa fa-angle-down u-header__nav-link-icon"></i>
</a>
</li>
<!-- End Blog -->
<!-- Button -->
<li class="nav-item u-header__nav-item-btn">
<a class="btn btn-sm btn-contact" href="#signupModal" role="button"
data-modal-target="#signupModal"
data-overlay-color="#151b26">
<i class="fa fa-user-circle mr-1"></i>
Contactez nous
</a>
</li>
<!-- End Button -->
<!-- Button -->
<li class="nav-item u-header__nav-item-btn">
<a class="btn btn-sm btn-primary" href="#signupModal" role="button"
data-modal-target="#signupModal"
data-overlay-color="#151b26">
<i class="fa fa-user-circle mr-1"></i>
Connexion recruteurs
</a>
</li>
<!-- End Button -->
</ul>
</div>
<!-- End Navigation -->
<ul class="navbar-nav flex-row u-header__secondary-nav">
<!-- Account Signin -->
<li class="nav-item u-header__navbar-icon">
<!-- Account Sidebar Toggle Button -->
<a id="sidebarNavToggler" class="btn btn-xs btn-icon btn-text-dark" href="javascript:;" role="button"
aria-controls="sidebarContent"
aria-haspopup="true"
aria-expanded="false"
data-unfold-event="click"
data-unfold-hide-on-scroll="false"
data-unfold-target="#sidebarContent"
data-unfold-type="css-animation"
data-unfold-animation-in="fadeInRight"
data-unfold-animation-out="fadeOutRight"
data-unfold-duration="500">
<i class="fa fa-bars btn-icon__inner font-size-13"></i>
</a>
<!-- End Account Sidebar Toggle Button -->
</li>
<!-- End Account Signin -->
</ul>
</nav>
<!-- End Nav -->
</div>
</div>
</header>
<!-- ========== END HEADER ========== -->
@@ -0,0 +1,240 @@
{% extends 'base.html.twig' %}
{% block title %}Talents Tube : Le 1er job board 100% vidéo{% endblock %}
{% block content %}
<div id="wrapper" class="no-padding-top no-padding-bottom">
<div class="fluid-container">
<div class="row flexcontainer row-noMargin">
{# VIDEO #}
<div class="col l12 m12 s12 home-content col-noPadding">
<div id="homeTeaser" class="valign-wrapper">
<h1 class="white-text center-align">1ère plateforme pour lemploi
<span>100% vidéo</span></h1><br/>
<div class="link-home-head">
<a data-target="modal_concept" href="#!" class="btn btn-default btn-round btn-concept modal-trigger">
Le concept en vidéo &nbsp;&nbsp;&nbsp;
<img src="{{asset('img/bouton-play.png')}}"/>
</a>
</div>
<div class="header-video-inner">
<video loop="" preload="metadata" autoplay="" id="vid" muted="muted">
<source src="/img/home_video.mp4" type="video/mp4">
</video>
</div>
</div>
{# RECHERCHE #}
<div class="fluid-container bg-grey-3 homeSearchWrapper">
<div id="homeSearch" class="container">
{% include 'form/search_form.html.twig' with {
'searchform' : searchform
} %}
</div>
</div>
{# BLOC OFFRE EMPLOI CARDS #}
<div id="liste-jobs" class="fuild-container bg-grey-3 button-plus">
<div class="container">
<div class="row center-align">
<div class="col s12">
<h2 class="blue-text no-margin-top">Les offres d'emploi</h2>
<h3 class="subtitles-homepage">Postulez en CV vidéo ou vidéo de motivation</h3>
</div>
</div>
<div class="row">
<div class="col s12 col-noPadding">
<div class="owl-carousel owl-carousel-home">
{% if ads | length > 0 %}
{% include 'default/ad_card.html.twig' with {
'ads' : ads
} %}
{% endif %}
</div>
</div>
</div>
<div class="row center-align">
<div class="col s12">
<a href="{{ path('ad_search_result') }}" title="Découvrir toutes les offres d'emploi" class="btn btn-default btn-round btn-all-jobs">Voir les offres
</a>
</div>
</div>
</div>
</div>
{# COMPANY #}
<div id="liste-company" class="bg-white button-plus">
<div class="container">
<div class="row center-align">
<div class="col s12">
<h2 class="blue-text no-margin-top">Ils recrutent</h2>
<h3 class="subtitles-homepage">Ils méritent votre candidature spontanée, découvrez leur réalité, leur marque employeur.</h3>
</div>
</div>
<div class="row">
<div class="col s12 col-noPadding">
<div class="owl-carousel owl-carousel-home home-company-carousel">
{% if companies | length > 0 %}
{% include 'default/company_card.html.twig' with {
'companies' : companies
} %}
{% endif %}
</div>
</div>
</div>
<div class="row center-align">
<div class="col s12">
<a href="{{ path('company_list') }}" title="Toutes les entreprise" class="btn btn-default btn-round btn-all-talents">Voir les entreprises</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{# TALENTS #}
<div id="liste-talents" class="bg-dark2 button-plus">
<div class="container">
<div class="row center-align">
<div class="col s12">
<h2 class="blue-text no-margin-top">Les talents à la une</h2>
</div>
<h3 class="subtitles-homepage">Découvrez leur CV vidéo et vidéo de motivation.</h3>
</div>
<div class="row">
<div class="owl-carousel owl-carousel-home home-talent-carousel">
{% if talents | length > 0 %}
{% include 'default/talent_card.html.twig' with {
'talents' : talents
} %}
{% endif %}
</div>
</div>
<div class="row center-align">
<h2>Rejoignez une communauté de plus de <strong>1000</strong> candidats</h2>
<div class="col s12 m-t-50">
<a href="#!" title="Créer Mon profil" class="btn btn-default btn-round btn-create-account">Créer mon profil</a>
</div>
</div>
</div>
</div>
{# TERRITOIRE #}
<div id="liste-territoires" class="bg-dark1 button-plus">
<div class="container">
<div class="row center-align">
<div class="col s12">
<h2 class="blue-text no-margin-top">Les territoires</h2>
<h3 class="subtitles-homepage">Venez vivre et travailler chez nous.</h3>
{% if territories %}
<div class="owl-carousel owl-carousel-home territory-carousel">
{% for t in territories if t.presentationVideo and t.isPrivate != true %}
<div class="item">
{% if t.presentationVideo.thumbnails.0. sizes is defined %}
<a href="{{ path('territory_show',{'alias': t.alias }) }}" title="{{ t.brandname }}">
<img src="{{ t.presentationVideo.thumbnails.0.sizes.4.link }}" alt="{{ t.brandName }}" class="overlay-hover"/>
<span class="playerbtn" style="margin-top: -55px;"></span>
</a>
{% endif %}
{% if t.extra.terType is defined %}
<div class="m-t-15 fs-12 text-100">{{ t.extra.terType|upper }}</div>
{% endif %}
<div class="m-t-5 hover-none">
<a href="{{ path('territory_show',{'alias': t.alias }) }}" class="color-white td-none">{{ t.brandName|upper }}</a>
</div>
</div>
{% endfor %}
</div>
<div class="m-t-30">
<a title="Voir les territoires" class="btn btn-default" href="{{ path('territory_list') }}">
<span>
Voir les territoires</span>
</a>
</div>
{% endif %}
</div>
</div>
</div>
</div>
{# BLOC contenu vidéo #}
<div class="fluid-container bg-grey-3">
<div class="container">
<div class="blocs-texte-video">
<div class="row center-align">
<div class="col s12">
<h2 class="blue-text no-margin-top no-margin-bottom">Les conseils de votre
<span>talentstubeuse</span></h2>
</div>
</div>
<div class="row flexcontainer row-bloc-video-1 row-noMargin">
<div class="col l6 m12 s12 col-noPadding">
<a href="#!" data-video="#video2" class="img_content embed-responsive embed-responsive-16by9" style="background:url(/img-cnt/cv_video.jpg);background-size:cover;">
<span class="playerbtn"></span>
</a>
<iframe style="display:block;" class="hide" id="video2" src="https://player.vimeo.com/video/286344340?title=0&byline=0&portrait=0" width="100%" height="344" frameborder="0" webkitallowfullscreen="webkitallowfullscreen" mozallowfullscreen="mozallowfullscreen" allowfullscreen="allowfullscreen"></iframe>
</div>
<div class="col l6 m12 s12 valign-wrapper">
<div class="inside-m valign">
<h2 class="no-margin-top">CV vidéo
</h2>
<p>Devenez acteur de vos talents, montrez qui vous êtes !</p>
</div>
</div>
<div class="clearfix"></div>
</div>
<div class="row flexcontainer row-bloc-video-2 row-noMargin">
<div class="col l6 m12 s12 valign-wrapper">
<div class="inside-m valign">
<h2 class="no-margin-top">
Marque Employeur et Offre d'emploi en vidéo
</h2>
<p>Développez votre Marque Employeur !</p>
</div>
</div>
<div class="col l6 m12 s12 col-noPadding">
<a href="#!" data-video="#video1" class="img_content embed-responsive embed-responsive-16by9" style="background:url(/img-cnt/offre_emploi.jpg);background-size:cover;">
<span class="playerbtn"></span>
</a>
<iframe style="display:block;" class="hide" id="video1" src="https://player.vimeo.com/video/215657499?title=0&byline=0&portrait=0" width="100%" height="344" frameborder="0" webkitallowfullscreen="webkitallowfullscreen" mozallowfullscreen="mozallowfullscreen" allowfullscreen="allowfullscreen"></iframe>
</div>
<div class="clearfix"></div>
</div>
<div class="row flexcontainer row-bloc-video-3 row-noMargin">
<div class="col l6 m12 s12 col-noPadding">
<a href="#!" data-video="#video3" class="img_content embed-responsive embed-responsive-16by9" style="background:url(https://i.vimeocdn.com/video/653721887_1024x573.jpg);background-size:cover;">
<span class="playerbtn"></span>
</a>
<iframe style="display:block;" class="hide" id="video3" src="https://player.vimeo.com/video/232618030" width="100%" height="344" frameborder="0" webkitallowfullscreen="webkitallowfullscreen" mozallowfullscreen="mozallowfullscreen" allowfullscreen="allowfullscreen"></iframe>
</div>
<div class="col l6 m12 s12 valign-wrapper">
<div class="inside-m valign">
<h2 class="no-margin-top">
Le territoire en vidéo
</h2>
<p>Développez votre Marque Territoire !</p>
</div>
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
{% include 'testimony/testimony_list.html.twig' %}
</div>
<div id="modal_concept" class="modal modal-fixed-footer">
<div class="modal-content">
<div class="video-container">
<iframe id="iframe_concept" src="https://player.vimeo.com/video/215638758?title=0&byline=0&portrait=0" frameborder="0" webkitallowfullscreen="webkitallowfullscreen" mozallowfullscreen="mozallowfullscreen" allowfullscreen="allowfullscreen"></iframe>
</div>
</div>
<div class="modal-footer">
<a href="#!" class="modal-action modal-close btn btn-default button-round-small">Fermer</a>
</div>
</div>
{% endblock %}
{% block javascripts %}
{{ parent() }}
<script src="https://player.vimeo.com/api/player.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDYV8IJGtIoWLfXJQQvIuDQ88n2aEuRgpg&libraries=places"></script>
{% endblock %}
@@ -0,0 +1,20 @@
{% extends 'base.html.twig' %}
{% block metarobot %}
{% if robot is defined and robot == 0 %}
<meta name="robots" content="noindex,nofollow">
{% else %}
<meta name="robots" content="index,follow">
{% endif %}
{% endblock %}
{% block title %}{{ page.title }}{% endblock %}
{% block description %}{{ page.description }}{% endblock %}
{% block content %}
{{ page.content|raw }}
{% if isTestimony is defined %}
{% include 'testimony/testimony_list.html.twig' %}
{% endif %}
{% endblock %}
@@ -0,0 +1,10 @@
<!-- props_settings.html.twig Parameters used in EdeclicPushAndNotificationClient.js -->
<div id="pushParams"
data-service-worker-url="{{ app.request.uriForPath('/Edeclic-service-worker.js') | replace({'/app_dev.php': ''}) }}"
data-analytics-helper-url="{{ app.request.uriForPath('js/analytics-helper.js') | replace({'/app_dev.php': ''}) }}"
data-delete-subscription-url="{{ url('delete-subscription') }}"
data-save-subscription-url="{{ url('save-subscription') }}"
data-push-public-key="{{ push_public_key }}"
>
</div>
@@ -0,0 +1,9 @@
<div class="bg-grey-3" style="height:1px;padding-top:150px;padding-bottom:10px;"></div>
<div class="triggerSearch"></div>
<div class="fluid-container bg-grey-3 searchBarWrapper">
<div id="homeSearch" class="searchBar container" style="top:0;">
{% include 'form/search_form.html.twig' with {'searchform': searchform } %}
</div>
</div>
@@ -0,0 +1,31 @@
{% for talent in talents %}
{% if talent.users[0] is defined %}
{% set user = talent.users[0] %}
<div class="item">
<a href="{{ path('talent_show',{'alias': talent.alias }) }}"
title="{{ user.firstname }} {{ user.lastname }}">
{% if user.socialPicture is not null and user.photo is null %}
<img class="circle z-depth-3" src="{{ user.socialPicture }}" alt="{{ user.firstname }} {{ user.lastname }}"/>
{% elseif user.photo %}
<img class="circle z-depth-3" src="{{ user.webPath | imagine_filter('profile_square') }}" alt="{{ user.firstname }} {{ user.lastname }}"/>
{% else %}
<div class="circle-letters font-2">{{ user.firstname|first|upper }}{{ user.lastname|first|upper }}</div>
{% endif %}
</a>
<p class="item-list-job item-list-name center-align">
<a href="{{ path('talent_show',{'alias': talent.alias }) }}"
title="{{ user.firstname }} {{ user.lastname }}">
{{ user.firstname }} {{ user.lastname }}
</a>
</p>
{#{% if talent.publicTag %}
{% for keyword in talent.publicTag %}
{% if keyword != "" %}
<div class="chip">{{ keyword }}</div>
{% endif %}
{% endfor %}
{% endif %}#}
</div>
{% endif %}
{% endfor %}
@@ -0,0 +1,9 @@
{% if is_granted('ROLE_PREVIOUS_ADMIN') %}
<div class="fab tooltipped" data-position="left"
data-tooltip="Quitter (Connecté en tant que {{ app.user.firstname }} {{ app.user.lastname }})">
<a href="{{ path('admin_dashboard', {'_switch_user': '_exit'}) }}"
class="btn">
<i class="fa fa-sign-out" aria-hidden="true"></i>
</a>
</div>
{% endif %}
@@ -0,0 +1,26 @@
{% for vid in videos %}
<div class="col s3">
<div class="card z-depth-1 card-video">
{#<div class="card-title-video">#}
{#<div class="row row-noMargin">#}
{#<div class="col s12 col-infos">#}
{#<div class="truncate">#}
{#{{ vid.title }}#}
{#</div>#}
{#</div>#}
{#</div>#}
{#</div>#}
<div class="card-image">
<iframe src="https://player.vimeo.com{{ vid.getCdnUrl()|replace({ "videos": "video"}) }}"
width="100%" height="auto" frameborder="0" webkitallowfullscreen
mozallowfullscreen allowfullscreen></iframe>
</div>
<a class="card-button addExistingVideo tooltipped" data-position="top"
data-tooltip="Choisir cette vidéo" href="#" data-title="{{ vid.getTitle() }}"
data-id="{{ vid.getId() }}">
{#<div class="w-100">Sélectionner</div>#}
<div class="w-100 truncate"><i class="fa fa-angle-double-right" aria-hidden="true"></i> {{ vid.title }}</div>
</a>
</div>
</div>
{% endfor %}
@@ -16,7 +16,11 @@
<br/>
<br/>
<div style="text-align:center;">
<a class="btn btn-default" href="{{ absolute_url(path('talent_ad_detail',{'alias': answer.ad.alias,'id': answer.id })) }}">Visionner la réponse vidéo</a>
{% if answer.ad.alias is null %}
<a class="btn btn-default" href="{{ absolute_url(path('talent_ad_detail',{'alias': aliasCompany,'id': answer.id })) }}">Visionner la réponse</a>
{% else %}
<a class="btn btn-default" href="{{ absolute_url(path('talent_ad_detail',{'alias': answer.ad.alias,'id': answer.id })) }}">Visionner la réponse</a>
{% endif %}
</div>
{% else %}
<br />
@@ -26,7 +30,11 @@
<br/>
<br/>
<div style="text-align:center;">
<a class="btn btn-default" href="{{ absolute_url(path('talent_ad_detail',{'alias': answer.ad.alias,'id': answer.id })) }}">Consulter la réponse</a>
{% if answer.ad.alias is null %}
<a class="btn btn-default" href="{{ absolute_url(path('talent_ad_detail',{'alias': aliasCompany,'id': answer.id })) }}">Consulter la réponse</a>
{% else %}
<a class="btn btn-default" href="{{ absolute_url(path('talent_ad_detail',{'alias': answer.ad.alias,'id': answer.id })) }}">Consulter la réponse</a>
{% endif %}
</div>
{% endif %}
<br>
@@ -8,7 +8,11 @@
<div id="preview_video">
{% if video is defined %}
{% if video is not null %}
<iframe src="https://player.vimeo.com{{ video.getCdnUrl()|replace({ "videos": "video"}) }}" width="100%" height="300px" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
<iframe
src="https://player.vimeo.com{{ video.getCdnUrl()|replace({ "videos": "video"}) }}"
width="100%" height="300px" frameborder="0"
webkitallowfullscreen mozallowfullscreen allowfullscreen>
</iframe>
{% endif %}
{% endif %}
</div>
@@ -0,0 +1,23 @@
{% extends 'base.html.twig' %} {% block content %}
<div id="page-static" class="contentWrapper">
<h1 class="alttitle center-align">Test PUSH</h1>
<div class="fluid-container bg-dark2">
<div class="container">
<div class="row first-row">
<div class="col s12 m6 video-wrapper">
<div class="video-container">
<img src="/img/img_content/accompagnement_img.png" alt="accompagnement">
</div>
</div>
<div class="col s12 m6">
<h5 class="m-t-0">TEST PUSH</h5>
<p>
</p>
<p>
</p>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
@@ -18,11 +18,3 @@
</div>
{% endblock %}
{% block javascripts %}
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDYV8IJGtIoWLfXJQQvIuDQ88n2aEuRgpg&libraries=places"></script>
{% javascripts
'@talents'
output='assetic/main.dashboard.talent.js' filter='?uglifyjs2' %}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}
{% endblock %}
@@ -1,8 +1,8 @@
{% extends 'talent/base_dashboard_talent.html.twig' %}
{% block dashContent %}
{% include 'default/props_settings.html.twig' %}
{% include 'default/flash_message.html.twig' %}
<div class=" row bg-bordered p-20">
{#<h1 class="alttitle">{{ 'profile.talent.account.title'|trans }}</h1>#}
@@ -11,18 +11,71 @@
<h4>{{ 'company.account.password.modify'|trans }}</h4>
{% if form_errors(formPw) %}
<div class="card-panel">
<span class="red-text text-darken-2">
{{ form_errors(formPw) }}
</span>
<span class="red-text text-darken-2">
{{ form_errors(formPw) }}
</span>
</div>
{% endif %}
{{ form_start(formPw) }}
{{ form_rest(formPw) }}
<br/>
<input class="btn btn-default" type="submit"
value="{{ 'company.account.password.modify.label'|trans }}"/>
<input class="btn btn-default" type="submit" value="{{ 'company.account.password.modify.label'|trans }}"/>
{{ form_end(formPw) }}
</div>
</div>
</div>
<div class=" row bg-bordered p-20">
<div class="row flexcontainer">
<div class="col s12">
<h4>{{ 'company.account.notifications.title'|trans }}</h4>
<br/>
<input type="checkbox" id="notificationChecked" name="notificationChecked" {{isNotificationAllowed ? "checked=checked":""}}/>
<label for="notificationChecked">Autoriser les notifications</label>
</div>
</div>
</div>
{% endblock %}
{% block javascripts %}
{{ parent() }}
<script type="text/javascript">
$('#notificationChecked').on('click', function (event) {
let EdeclicLib = window.EdeclicLib;
let notifConsent = $('#notificationChecked').is(":checked");
if (notifConsent == true) {
//ask for subscription
var promise1 = new Promise(EdeclicLib.askForNotifications)
.then(() => $('#notificationChecked').prop('checked', true), () => $('#notificationChecked').prop('checked', false))
.catch((err) => {
$('#notificationChecked').prop('checked', false);
alert(err);
});
} else {
//require unsubscription
EdeclicLib.unsubscribe();
$.ajax({
async: true,
type: 'POST',
url: '{{ url('talent_notification_consent') }}',
data: JSON.stringify({'notificationConsent': false}),
success: function (data) {
data = JSON.parse(data);
$('#notificationChecked').prop('checked', data['notificationConsent']);
},
contentType: "application/json",
dataType: 'json'
});
}
});
</script>
{% endblock %}
@@ -5,7 +5,8 @@ assetic:
filters:
cssrewrite: ~
uglifyjs2:
bin: /usr/local/bin/uglifyjs
#bin: /usr/lib/node_modules/uglify-es/bin/uglifyjs
bin: /usr/local/bin/uglifyjs #sym linked in container (see makefile)
assets:
vendors:
inputs:
@@ -25,6 +26,9 @@ assetic:
- 'js/global.js'
- 'js/register.js'
- 'js/tags.js'
- 'js/EdeclicTools.js'
- 'js/EdeclicPushAndNotificationClient.js'
company:
inputs:
- 'js/company.js'
@@ -42,6 +46,8 @@ assetic:
- 'js/vendors/datepicker.min.js'
- 'js/vendors/jquery.validate.min.js'
- 'js/talent.js'
- 'js/EdeclicTools.js'
- 'js/EdeclicPushAndNotificationClient.js'
admin:
inputs:
- 'admin/AdminLTE/plugins/jQuery/jquery-2.2.3.min.js'
+67 -4
View File
@@ -51,7 +51,8 @@ doctrine:
password: "%database_password%"
charset: UTF8
orm:
auto_generate_proxy_classes: "%kernel.debug%"
#auto_generate_proxy_classes: "%kernel.debug%"
auto_generate_proxy_classes: false
entity_managers:
default:
connection: default
@@ -77,6 +78,7 @@ twig:
debug: "%kernel.debug%"
strict_variables: "%kernel.debug%"
globals:
push_public_key: "%push_params.public_key%"
fairlane_cookie_consent: '@fairlane_cookie_consent.twig'
@@ -104,7 +106,7 @@ fos_user:
email:
template: email/password_resetting.email.twig
from_email:
address: noreply@talentstube.com
address: noreply@talentstube.io
sender_name: talentstube.com
service:
mailer: fos_user.mailer.twig_swift
@@ -191,8 +193,12 @@ hwi_oauth:
resource_owners:
facebook:
type: facebook
# PROD
client_id: 1800752833559014
client_secret: 454de729b1e58f506f94c8b50ca5c011
client_secret: 454de729b1e58f506f94c8b50ca5c011
#DEV TT app
# client_id: 2332071840142634
# client_secret: afb8bbca72bd8c517c64f81e998e4f12
scope: "email, public_profile, user_birthday"
infos_url: "https://graph.facebook.com/me?fields=id,email,first_name,last_name,gender,birthday,picture.type(square)"
paths:
@@ -227,4 +233,61 @@ monolog:
level: debug
type: rotating_file
max_files: 15
path: '%kernel.logs_dir%/%kernel.environment%_debug.log'
path: '%kernel.logs_dir%/%kernel.environment%_debug.log'
#Api
fos_rest:
zone:
- { path: ^/api/* }
body_converter:
enabled: true
view:
formats: { json: true, xml: false, rss: false }
view_response_listener: true
mime_types:
json: ['application/json', 'application/json;version=1.0', 'application/json;version=2.0']
serializer:
serialize_null: true
format_listener:
rules:
- { path: '^/api/talent', priorities: ['html'], fallback_format: 'html' }
- { path: '^/api/', priorities: ['json'], fallback_format: 'json' }
param_fetcher_listener: true
exception:
enabled: true
codes:
{ 'AppBundle\Exception\ResourceValidationException': 400 }
messages:
{ 'AppBundle\Exception\ResourceValidationException': true }
lexik_jwt_authentication:
secret_key: '%kernel.root_dir%/../app/config/jwt/private.pem' # required for token creation
public_key: '%kernel.root_dir%/../app/config/jwt/public.pem' # required for token verification
pass_phrase: 'talentstubeforever' # required for token creation, usage of an environment variable is recommended
token_ttl: 3600000
token_extractors:
# look for a token as Authorization Header
authorization_header:
enabled: true
prefix: Bearer
name: Authorization
# check token in a cookie
cookie:
enabled: false
name: BEARER
# check token in query string parameter
query_parameter:
enabled: true
name: bearer
nelmio_cors:
paths:
'^/':
allow_credentials: true
allow_origin: ['*']
allow_headers: ['Origin', 'X-Requested-With', 'Content-Type', 'Accept', 'Authorization']
allow_methods: ['POST','GET','DELETE','PUT']
expose_headers: []
max_age: 3600000
@@ -1,6 +1,7 @@
fos_elastica:
clients:
default: { host: %elastic_host%, port: %elastic_port% }
indexes:
tags:
types:
@@ -139,4 +140,5 @@ fos_elastica:
driver: orm
model: AppBundle\Entity\User
provider: ~
finder: ~
finder: ~
@@ -0,0 +1,54 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,1B8B1CB3A64B49F820DD713907974037
0/ahxIYlJ0RiiOqRz78LbR7g+UvBC8r4RrMWFCIOuh/FPbTYyIc0VxRMObrTqvHv
B4oUMnTzHzkOimvLWncZSIA39TL2OuQMTT7g/Cp8uh7Exnf29js7Ywv8EAQA2trw
EsLXjH5St3vLhWLQdxVUBY6tWc5yuqTJ3ze9rFojiJ0mbIoeid7L8sI4mQAocfX2
2/aMWwhQX83AJaRC7liU18nZAP4gAxYjvLAaC6zj7M3wxPv1r3Ox2PuSUfYZFkYA
HbVYq6pi/Dw32CmCniufccSr2wd0f78fZdI/E20tdAviLN6awqrjM2aFgzqZ6zw/
UCD3L1hLfGxRk6uYAFgEiFQB7dT4ZzqjopKNsVuho+DTc55kmx8iPD3xXuTMbeUY
SgiV4KcGCbHRt1HGWWbJgyOkSaPQQQk5Bf63glS4nLVNqzIqzJmpVCKuwOpKCSnK
DTeWpw9MIHLHM4SD2OM8Hh8S8l6v+Y4ash6mEtUNh6a7N+TQ1vEn/wyt8wyM7/Fh
UY/97loUyu0HC2Ox89sP1y6VcNaRQlhNj9hZzLC/q5K+Z4zAQRnGPuTowZL7ztxZ
BD+MTnNZc+Akrti+3c1vAHxzuUoBd7h8NX2pnNNUY2Wme9JqfZnCx9fV4AwVOvx6
8mvTQL5YHOv8HpsGnDoOak1r+QzHM8IrL8SSrJ/DBXMIWmFefhcIDgrXZG8LV+ck
RlSuP5Lsyy3e8AQ6hrM06DXkhjGi7gCeHIHySbzw0AiFERQz0d7XgU75DL/ALPqh
0lyqlXdrx/+qqTc0wwjYIerNLNdVqN9kvLg+aqFSwZrfiZyEy6rYdUoqYXoInwle
QBt2uqcjVUhMwdQYaDWiqHidSpIMP5nuTKDm6Z8J/SLf4iy+It1qXUEcoRKhDavm
fy+dw3JvthpoNjP3Bq+moygP8J8msS5Ti3UgVug21Fsp89fmvUO8FO2JRXLXP8+U
3HG1Ij/KKk1dxC6PT7qu9gVeoKM+W8maCVV/O84Qx/N3aXY+sHm1HsSssg0cLEC7
zaEai16xhVGI8aagYwxBHVkVVXk/CBS7zq1JYBnZOIw56d1NTjvJ3YmTx619Hyek
PJuMNjGV4mM0jONzHJbI6deE2B+f1/ej1JwoeGyBhynrZjwtTCd3JAtwRK9WO1fq
owdoCAnDOV7yDcwfFEYaNV2ie/R/kQo/fIIanykQs59Op2M0yhLvmch+C3RghLVg
qfR3Jngbqjwz/uh5ZQShZtHFirdAyer/eLD0CteDt4TrAiQxiHqrEOdqwF/G/STq
+3SSkChf6uhqUUqfmJFwxaF6AiNTkdk0YyxucWY2JXYf3qyz7ADGnI/KZZ+1LchF
2bLUKjyjnFKQoaFtDd7qMGxrTD80egN/fFV4Nybt+DTsGjdUjvCFS69j+YvZ0vIP
8rZHK7etISTfiauP9SrIR9UKpNA8fGrUgJGOMo/5Wkz4YS6LmMceQkpDxj46p8Ia
Iv+pOKez6NsckP1OiDfTxLtXL1S3xQHP3V0dYI5UcWt8Bczi2VylZCcS8JiV8Cqy
+EYRaIB9Qi1X5uLQsbiyS70rJp9mJ3xUR2dIzD70njCIDtLPA2b9dXqXm1IyqdkB
46W0MOnyI699XgiywvPovwhzTH8uO5Xn5gnjEgD92pHdJ2iTVQDTC9qtKhODrhbC
ouOCbS/LPAnQMwlLD1rWAeJcBJ3PL1KdAlaxWq3Jd/iMhDh/hSboS88Lm88RYtBh
3DhMCyxY1gu6jyzuWN2pHKzCvZ1Aqqm1SMS/8nAPe/KtPJO7zTRQJIrrfPK1pt2B
u5tu1zupVKihoRkLZtV4FUwDBo8DE9V65b/LAJZtuId77ci7aWRoD5b1Lc9X9iyH
cFJTQbMxzA76/8F9/Y1h8D9mdP+N9Tfw6iOvRxszqciGAsUasqo4Xm3ZOQqCcOo5
djoywGnzqsfxrV733i2KHRqz7XUkLf8n6URloH2i1tSbHWl7fmYAC0N85IUs1PxQ
DB0LUtQgS03gjE4pRJSlgf8JX/0KrG8sYpcvz9R5CqMKrkM6rDy6ehe4P5xVQ+3m
WNCZFfGjCTcuEVLFDNx8CdF8qIV/BCcUSty7KXXoC3AMOAsVlZSwskmKN61GJmBS
Sz1bDwZO6QCZgXR2fH0UMEnCkpksS4xf3f0oq5/WzWzC4ZaDHnwt5NqKE8XXeYpn
isulqUFmCK2VhkqRX1rwND8E45yDG8+U5lyJSHp4y8Fe+AEQjxXUxXDefc80s09i
LMXM7iNUtESFge3BZvocdRrqvp21tkPElzaDoW0nMb0VoNI4Xfe113vBeBdEq0Hr
yuGvM8ZgvKjzl1T4h9PTaBu97kR1QjBSiY0PeEeSMtq/W1XbFO5jU4g/utVRluBm
z64kldtRW1RC8vosrN4sNbdVDAvL43Dynl0wYMI+jgIN3HP2QnOTDH1MLQ5BJZg4
aZFSMZ70e9kF2HXpFnfp+SsuT0lMhzZrSrLvKg0pkuD8jc7FtP/HoLcay2doBufd
fS4VheiaGm7om9Ggmkowld1CUpuzfyi7NDcymWH6J37Ypcvprn1Ts9iBcBDaOsbZ
T3pP0mU4glmRPFRq2IRZXOgTQFXIJKYFpnt0LCC2IuzbQLTKy0LVr6Ksc6ZD21j5
AR/xblSp8dZDS4ltrN44r+rtcio7dN9KlDctURpoqdw8oatwpk5QLFfYeMKPRn6j
yQA4tatWlTxr/UR8Xy8JNcJfg7JQIYjdf36atxpv5xYvnkf6Gs56xVnRthwNYawn
h44emyq/Tuflc9FZqptUDwEPKzLvH0NWxVkNvGG92H0OtES3q9OpGPTnqhIPUTme
Jrbu7knwD5sdzYRh64BhbXem8glPStYnW7B0dSdvyvGpArF1W2cKKURgnr7XokrB
DqbeSpdRf7fE5bw9jHJgcpUJOZ3o6kGA3l309Cdcbigm7gnK0KiY0y/P8MSWEu00
C4WZOFLxuaO1iVav+spACFbFkdVmLoRBPE2hFUc6BA3E/7qNHAjlVYXbUrIR3NA+
iioXf1XFM7K0LG02mMKEFSuWIpZacDyAfjHUlrid7cFBBXLk/EWcwNyGSlRdQl7w
rn7V+QfAdTxmk2FAyO80odbrdZQaBR6oLZaFgz/MzkT6dLJXwCjKG/qJrwwV/2sv
-----END RSA PRIVATE KEY-----
@@ -0,0 +1,14 @@
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0emZKHHTXLKphYp1XLeh
YApXdcWoZenqaFeE9pa3yzP888bsvka7t41JZy7+LOACkjnZj8VQNhMl/JIwtuv8
L276Tox94l1CeLSDvH0vxGAvCyZzpW4pgx2xAJk1xWndkEWcx/6A7/kgdePOFNJt
41JdDsefqRMlsMjw5vCxxX4V1mlebi6owKkxVBXii476xheX1M2k3cfVbC95h++h
Yd7h10DwA17SPbmIDN07QygKqRH7RGkEU5gK2Psc+NFstmYaYj4ew1NF4X9e2Erj
5M3RnYoUfkQBaigv+GSjefL6zdp+yZwjrPtZo+YDC/M1SQLEPAsoxQZvOISrLtkH
usqdvLB8rsVysZOipJyO3OClI+Vvqy9p4CggM3rHlpzMu+e+sgpZersaNxDEz/rX
J/rMXpPTfkVSRMddkQ/s0e0w4oop/tr2Zi4fYfmaJ2Ha49PFBPT7buZeyabLyAOk
utwRBkaGiUGmfVidlb0TMK2fQQOS5WottAJJOhEDzl7woCtCBgCeclsuM6v/EDd/
9KCeMcWrx7/PHBH2I8RGSfoqTKrZ8plOOPccaY2G6zZjvceExyBjewlzOm5zXI7Z
c/L5H9mghOdLjEJ+eRLZIYL9yw1LSDjY3Q0ENkxdvkMdVnZxmsf+UFMFdxBU3VjB
hqeH8T9lC2ZWC8OJ5kA4y4ECAwEAAQ==
-----END PUBLIC KEY-----
@@ -1,5 +1,6 @@
# This file is auto-generated during the composer install
parameters:
onurb_yuml.extension: jpg
mailer_transport: smtp
mailer_host: mail.gandi.net
mailer_user: noreply@talentstube.com
@@ -9,7 +10,7 @@ parameters:
database_port: '5432'
database_name: database
database_user: user
database_password: edcl56
database_password: b|RN:iR<g,TNMqM6
mongodb_server: 'mongodb://tt-website.mongo.dev:27017'
prestashop_key: 9YUQ5jPqT4Z4x5s9B25pb1yuGBtpaeBDxpWDgicPF3CuP8F2p9aK18ZS
prestashop_path: /home/projects/prestashop1/store
@@ -24,4 +25,14 @@ parameters:
media_photo_dir: '%kernel.root_dir%/../web/uploads/photos/'
elastic_host: tt-website.elasticsearch.dev
elastic_port: 9200
delivery_addresses: thomas@e-declic.com
delivery_addresses: thomas.berrod@e-declic.com
push_params:
push_notification_file_path: '%kernel.root_dir%/../web/push/'
push_network_config:
public_key: '%push_params.public_key%'
private_key: MgPlINZBO4yIQM8Op2QkQJZNLEuLYUkRhDsbm1a0IpE=
service_mail_subject: 'mailto:looping@talentstube.com'
ttl: 300
urgency: high
topic: Emploi
push_params.public_key: BNFyiyPiLH97Dgc0m1vXluUNaCN6y3Hkgd4YcqS2lVkP8my3tq2D5gM5g7cY6R4VxC7GljSzkLRu+k+oO+2TtjU=
@@ -8,8 +8,8 @@ parameters:
database_port: '5432'
database_name: database
database_user: user
#database_password: 7C|Uk2B[.>"6{QO{
database_password: b|RN:iR<g,TNMqM6
database_password: 7C|Uk2B[.>"6{QO{
#database_password: b|RN:iR<g,TNMqM6
#Mongo
mongodb_server: "mongodb://tt-website.mongo.preprod:27017"
#Prestashop
@@ -28,4 +28,14 @@ parameters:
elastic_host: tt-website.elasticsearch.preprod
elastic_port: 9200
delivery_addresses: thomas@e-declic.com
delivery_addresses: thomas.berrod@e-declic.com
push_params:
push_notification_file_path: '%kernel.root_dir%/../web/push/'
push_network_config:
public_key: '%push_params.public_key%'
private_key: M2KltnIzI3K89cYz4cjlYaOQjqcGlicqKuoga6YsZcc
service_mail_subject: 'mailto:looping@talentstube.com'
ttl: 300
urgency: high
topic: Emploi
push_params.public_key: BC9XGBLNGm0RWczR4IjEPWQ9_P1BmlvT-oaVgr_GJTI2OZtT85olmi3xzQhgZF4-Bi0rPafpa8vqt5pudQ4Na6w
@@ -27,4 +27,15 @@ parameters:
elastic_host: tt-website.elasticsearch.prod
elastic_port: 9200
delivery_addresses: thomas@e-declic.com
delivery_addresses: thomas.berrod@e-declic.com
push_params:
push_notification_file_path: '%kernel.root_dir%/../web/push/'
push_network_config:
public_key: '%push_params.public_key%'
private_key: g2Yimi3AK1ppvRqwikPyTTWcEEsTdRPxoBJ2Vi9bOWw
service_mail_subject: 'mailto:looping@talentstube.com'
ttl: 300
urgency: high
topic: Emploi
push_params.public_key: BG2lV673DvB67dzEwX9GKfds3sXaEdtZo2oWO1cO2xUdTJAFZ_rV_UrP1nHQz-F8LJNO9HxG0kmQRIb54JL1ZCA
@@ -38,4 +38,17 @@ parameters:
# Elastic
elastic_host: tt.search_db
elastic_port: 9200
elastic_port: 9200
#Push
push_params:
#don't forget trailing slash for dir
push_notification_file_path: '%kernel.root_dir%/../web/push/'
push_network_config:
public_key: 'BNFyiyPiLH97Dgc0m1vXluUNaCN6y3Hkgd4YcqS2lVkP8my3tq2D5gM5g7cY6R4VxC7GljSzkLRu+k+oO+2TtjU='
private_key: 'MgPlINZBO4yIQM8Op2QkQJZNLEuLYUkRhDsbm1a0IpE='
service_mail_subject: 'mailto:thomas.berrod@e-declic.com'
ttl: 300
urgency: 'high'
topic: 'Emploi'
push_params.public_key: 'BNFyiyPiLH97Dgc0m1vXluUNaCN6y3Hkgd4YcqS2lVkP8my3tq2D5gM5g7cY6R4VxC7GljSzkLRu+k+oO+2TtjU='
delivery_addresses: thomas.berrod@e-declic.com
@@ -20,6 +20,12 @@ hwi_oauth_connect:
hwi_oauth_redirect:
resource: "@HWIOAuthBundle/Resources/config/routing/redirect.xml"
prefix: /login
bentools_webpush:
resource: '@WebPushBundle/Resources/config/routing.xml'
prefix: /webpush
fairlane_cookie_consent:
resource: "@FairlaneCookieConsentBundle/Resources/config/routing.yml"
resource: "@FairlaneCookieConsentBundle/Resources/config/routing.yml"
api_login_check:
path: /api/login_check
@@ -13,3 +13,7 @@ _errors:
_main:
resource: routing.yml
doctrine_yuml:
resource: "@OnurbYumlBundle/Resources/config/routing.yml"
prefix: /my_prefix/
+31 -1
View File
@@ -5,12 +5,31 @@ security:
fos_userbundle:
#id: fos_user.user_provider.username_email
id: app.user_provider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
api_login:
pattern: ^/api/login_check
stateless: true
anonymous: true
provider: fos_userbundle
json_login:
check_path: /api/login_check
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
api:
pattern: ^/api
stateless: true
anonymous: true
provider: fos_userbundle
guard:
authenticators:
- lexik_jwt_authentication.jwt_token_authenticator
main:
pattern: ^/
remember_me:
@@ -33,6 +52,8 @@ security:
anonymous: true
switch_user:
provider: fos_userbundle
access_control:
- { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, roles: IS_AUTHENTICATED_ANONYMOUSLY }
@@ -44,6 +65,15 @@ security:
- { path: ^/talent/recherche/, roles: ROLE_COMPANY }
- { path: ^/entreprise/me/, roles: ROLE_COMPANY }
- { path: ^/territoire/me/, roles: ROLE_TERRITORY }
- { path: ^/api/login_check, roles: IS_AUTHENTICATED_ANONYMOUSLY}
- { path: ^/api/login_check_oauth, roles: IS_AUTHENTICATED_ANONYMOUSLY}
- { path: ^/api/register, roles: IS_AUTHENTICATED_ANONYMOUSLY, methods: [POST]}
- { path: ^/api/reset_password, roles: IS_AUTHENTICATED_ANONYMOUSLY, methods: [POST]}
- { path: ^/api/confirmAccount, roles: IS_AUTHENTICATED_ANONYMOUSLY, methods: [POST]}
- { path: ^/api/answers, roles: IS_AUTHENTICATED_FULLY, methods: [GET]}
- { path: ^/api/answer/[0-9]+/messages, roles: IS_AUTHENTICATED_FULLY, methods: [GET]}
- { path: ^/api, roles: IS_AUTHENTICATED_FULLY, methods: [POST, PUT, DELETE, PATCH] }
- { path: ^/api, roles: IS_AUTHENTICATED_ANONYMOUSLY, methods: [GET]}
encoders:
FOS\UserBundle\Model\UserInterface: bcrypt
+11 -1
View File
@@ -60,7 +60,7 @@ services:
class: AppBundle\Utils\Services\CompanyManager
arguments: ["@doctrine.orm.entity_manager", "@mt.slug"]
app.ad_manager:
app.ad_manager:
class: AppBundle\Utils\Services\AdManager
arguments: ["@doctrine.orm.entity_manager","@security.token_storage", "@mt.slug", "@app.mail_manager"]
@@ -83,3 +83,13 @@ services:
app.user_provider:
class: AppBundle\Security\Core\User\FOSUBUserProvider
arguments: ["@fos_user.user_manager","@doctrine.orm.entity_manager","@mt.slug","@service_container", { facebook: facebookId, linkedin: linkedinId}]
# PUSH
app.notification_sender:
class: AppBundle\Utils\Services\NotificationSender
arguments: ["@doctrine.orm.entity_manager","@fos_user.user_manager", "%push_params%"]
app.user_subscription_manager:
class: AppBundle\Utils\Services\UserSubscriptionManager
arguments: ["@doctrine.orm.entity_manager"]
app.api_key_authenticator:
class: AppBundle\Security\ApiKeyAuthenticator
+11 -4
View File
@@ -23,8 +23,8 @@
},
"require": {
"php": ">=5.5.9",
"symfony/symfony": "3.2.*",
"doctrine/orm": "2.6.*@dev",
"symfony/symfony": "^3.4",
"doctrine/orm": "^2.6.2",
"doctrine/doctrine-bundle": "^1.6",
"doctrine/doctrine-cache-bundle": "^1.2",
"symfony/swiftmailer-bundle": "^2.3.10",
@@ -37,7 +37,6 @@
"friendsofsymfony/user-bundle": "~2.0",
"doctrine/mongodb-odm-bundle": "^3.0",
"doctrine/mongodb-odm": "^1.0",
"alcaeus/mongo-php-adapter": "^1.0",
"dunglas/doctrine-json-odm": "dev-master",
"php-ffmpeg/php-ffmpeg": "^0.5",
"requestlab/vimeo-bundle": "^0.0.3",
@@ -51,8 +50,16 @@
"symfony/assetic-bundle": "^2.8",
"friendsofsymfony/elastica-bundle": "4.1.*",
"liip/imagine-bundle": "^1.9",
"bentools/webpush-bundle": "0.3.*",
"twig/extensions": "^1.5",
"fairlane/cookie-consent-bundle": "^1.0"
"fairlane/cookie-consent-bundle": "^1.0",
"jms/serializer-bundle": "^2.4",
"friendsofsymfony/rest-bundle": "^2.4",
"white-october/pagerfanta-bundle": "^1.2",
"willdurand/hateoas-bundle": "^1.4",
"lexik/jwt-authentication-bundle": "^2.5",
"nelmio/cors-bundle": "^1.5",
"onurb/doctrine-yuml-bundle": "^1.1"
},
"require-dev": {
"sensio/generator-bundle": "^3.0",
+3267 -649
View File
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,93 @@
<?php
namespace AppBundle\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\Common\Persistence\ManagerRegistry;
use Symfony\Component\Console\Input\InputOption;
class SendPushCommand extends ContainerAwareCommand
{
private const defaultEmail = 'lognone.gregoire@hotmail.fr';
protected function configure()
{
$this
->setName('app:push:send')
->setDescription('Send a push to Users by email, profile completeness, keywords matching.')
->setHelp(' ! Your user must have subscribed to push\n'.
' unless option -t, enter a .json file discribing your intent in the push dir.\n'.
' You can specify keywords OR profile completeness\n'.
' pushType can be "keyword" or "profile" or "general" or "users"\n'
)
->addArgument('email', InputArgument::OPTIONAL, 'The email of the user.')
->addOption(
'filename',
'f',
InputOption::VALUE_OPTIONAL,
'Name of file in the push directory "filename.json"',
'coriolis.json'
)
->addOption(
'test',
't',
InputOption::VALUE_NONE,
'Send a test to a defaultEmail '
)
->addOption(
'all',
'a',
InputOption::VALUE_NONE,
'Send push to all subscribed users'
);
}
protected function execute(InputInterface $input, OutputInterface $output)
{
// email pour test en dev
$email = $input->getArgument('email');
if ($email == null) {
$email = self::defaultEmail;
}
$filename = $input->getOption('filename');
$testOption = $input->getOption('test');
$globalOption = $input->getOption('all');
// $style = new OutputFormatterStyle('red', 'yellow', array('bold', 'blink'));
// $output->getFormatter()->setStyle('fire', $style);
$output->writeln([
'Push Sender',
'============',
$this->getContainer()->getParameter('kernel.root_dir'),
'============',
]);
$notificationManager = $this->getContainer()->get('app.notification_sender') ; //$this->getContainer()->get('app.product_manager');
//lpio
if($testOption !== false)
{
$output->writeln('sending a test probe to user (no config used) ---> '.$email );
$notificationManager->sendTestNotification($email, $filename, $output);
}
else if ($globalOption !== false)
{
//send globaly
$output->writeln('sending to all subscriptions');
$notificationManager->sendPushToAllSubscribedUsers($filename, $output);
}
else
{
$output->writeln('sending file description '.$filename.' to user ---> '.$email );
$output->writeln('Executing NotificationSender test script');
$notificationManager->sendSingleNotification($email, $filename, $output);
}
}
}
@@ -5,6 +5,7 @@ namespace AppBundle\Controller\Admin;
use AppBundle\Entity\Company;
use AppBundle\Entity\Product;
use AppBundle\Form\Admin\CompanyAdminType;
use AppBundle\Form\Admin\UserCompanyType;
use AppBundle\Form\TokenAddType;
use Edeclic\PrestashopBridgeBundle\Event\PrestashopBridgeEvents;
use Edeclic\PrestashopBridgeBundle\Event\UserEvent;
@@ -36,14 +37,26 @@ class CompanyController extends Controller
$user = $company->getUsers()->first();
$form = $this->createForm(CompanyAdminType::class, $company);
$form->handleRequest($request);
$formUser = $this->createForm(UserCompanyType::class, $user);
$formUser->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$companyManager = $this->get('app.company_manager');
$companyManager->updateCompany($company);
$event = new UserEvent($user);
$this->get('event_dispatcher')->dispatch(PrestashopBridgeEvents::USER_PROFIL_EDIT_SUCCESS, $event);
}
if ($formUser->isSubmitted() && $formUser->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
}
return $this->render('admin/company_edit.html.twig', array(
'form' => $form->createView(),
'formUser' => $formUser->createView(),
'company' => $company,
));
}
@@ -327,9 +327,11 @@ class AnswerController extends Controller
if ($answer->getAd() == null) {
$type = 'spontaneous';
$title = $answer->getCompany()->getBrandName();
$aliasCompany = $answer->getCompany()->getAlias();
} else {
$type = 'answer';
$title = $answer->getAd()->getTitle();
$aliasCompany = '';
}
$user = $this->getUser();
$form = $this->createForm(ContactTalentType::class);
@@ -365,6 +367,7 @@ class AnswerController extends Controller
'user' => $answer->getUser(),
'video' => $message->getVideo(),
'message' => $message,
'aliasCompany' => $aliasCompany
));
$plainView = $this->renderView('email/contact_talent_plain.html.twig', array(
@@ -0,0 +1,136 @@
<?php
namespace AppBundle\Controller\Api;
use AppBundle\Entity\Ad;
use AppBundle\Representation\Ads;
use AppBundle\Representation\SingleAd;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Controller\Annotations\Get;
use FOS\RestBundle\Controller\Annotations\Post;
use FOS\RestBundle\Controller\Annotations\View;
use FOS\RestBundle\Controller\FOSRestController;
use FOS\RestBundle\Request\ParamFetcherInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use JMS\Serializer\SerializationContext;
use Symfony\Component\HttpFoundation\JsonResponse;
class AdController extends FOSRestController
{
/**
* @Rest\Get(path="/api/ads/{id}", name="api_ad_show", requirements={"id"="\d+"})
* @Rest\View
*
*/
public function showAction(Ad $ad)
{
// return $ad;
//return new SingleAd($ad);
$data = $this->get('jms_serializer')->serialize($ad, 'json', SerializationContext::create()->setGroups(array('ad_detail')));
return new JsonResponse($data, 200, [], true);
}
/**
* @Rest\Get("/api/ads", name="api_ad_list")
*
* @Rest\QueryParam(
* name="keyword",
* requirements="\w+",
* nullable=true,
* description="The keyword to search for."
* )
* @Rest\QueryParam(
* name="order",
* requirements="asc|desc",
* default="asc",
* description="Sort order (asc or desc)"
* )
* @Rest\QueryParam(
* name="limit",
* nullable=true,
* requirements="\d+",
* default="15",
* description="Max number of ads per page."
* )
* @Rest\QueryParam(
* name="offset",
* nullable=true,
* requirements="\d+",
* default="1",
* description="The pagination offset"
* )
* @Rest\QueryParam(
* name="isPromoted",
* requirements="\d+",
* nullable=true,
* description="Ads are satisfied (pourvues) or not "
* )
*
* @Rest\QueryParam(
* name="isEmphasis",
* requirements="\d+",
* nullable=true,
* description="Ads are promoted -mise en avant"
* )
*
* @Rest\QueryParam(
* name="status",
* requirements="\w+",
* nullable=true,
* description="Ads filtered by status (PUBLISHED, DISABLE, DRAFT, CLOSED, DECLINED)"
* )
*
* @Rest\View(statusCode=200, serializerGroups={"ad_list"})
*/
public function listAction(ParamFetcherInterface $paramFetcher)
{
$pager = $this->getDoctrine()->getRepository('AppBundle:Ad')->search(
$paramFetcher->get('keyword'),
$paramFetcher->get('order'),
$paramFetcher->get('limit'),
$paramFetcher->get('offset'),
$paramFetcher->get('status'),
$paramFetcher->get('isPromoted'),
$paramFetcher->get('isEmphasis')
);
return new Ads($pager);
}
/**
* @Rest\Post("/api/ads", name="api_ad_create")
* @Rest\View(StatusCode = 201)
* @ParamConverter("ad", converter="fos_rest.request_body")
*/
public function createAction(Ad $ad)
{
$em = $this->getDoctrine()->getManager();
$em->persist($ad);
$em->flush();
return $this->view(
new SingleAd($ad),
Response::HTTP_CREATED,
['Location' => $this->generateUrl('api_ad_show', ['id' => $ad->getId(), UrlGeneratorInterface::ABSOLUTE_URL])]
);
}
/**
* @Rest\Get("/api/adAjaxRecStat/{id}", name="adAjaxRecStat")
* @Rest\View(statusCode=200)
*/
public function adAjaxRecStatAction(Ad $ad)
{
$history = $this->get('edeclic.history.record');
if ($this->getUser()) {
$idUser = $this->getUser()->getId();
$history->recordIt($idUser, "r", get_class($ad), $ad->getId(), serialize($ad));
} else {
$history->recordIt("Anonymous", "r", get_class($ad), $ad->getId(), serialize($ad));
}
return new JsonResponse(array('code' => "ok"));
}
}
@@ -0,0 +1,273 @@
<?php
namespace AppBundle\Controller\Api;
use AppBundle\Entity\Answer;
use AppBundle\Entity\Message;
use AppBundle\Entity\Company;
use AppBundle\Entity\user;
use AppBundle\Representation\Answers;
use AppBundle\Representation\SingleAnswer;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Controller\Annotations\Get;
use FOS\RestBundle\Controller\Annotations\Post;
use FOS\RestBundle\Controller\Annotations\View;
use FOS\RestBundle\Controller\FOSRestController;
use FOS\RestBundle\Request\ParamFetcherInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use JMS\Serializer\SerializationContext;
use AppBundle\Exception\ResourceValidationException;
use AppBundle\Exception\UnknownUserException;
use \DateTime;
class AnswerController extends FOSRestController
{
/**
* @Rest\Get(path="/api/answers/{id}", name="api_answer_show", requirements={"id"="\d+"})
* @Rest\View
*
*/
public function showAction(Answer $answer)
{
$usr = $this->getUser();
$userAnswer = $this->getDoctrine()->getRepository('AppBundle:Answer')->findOneByWithCorrespondences($usr, $answer->getId());
if ($userAnswer) {
$data = $this->get('jms_serializer')->serialize($answer, 'json', SerializationContext::create()->setGroups(array('answer_detail')));
return new JsonResponse($data, 200, [], true);
} else {
$message = 'Pas de candidature correspondante.';
$status = 'failure';
throw new ResourceValidationException($message, $status);
}
}
/**
* @Rest\Get("/api/answers", name="api_answer_list")
* @Rest\QueryParam(
* name="order",
* requirements="asc|desc",
* default="asc",
* description="Sort order (asc or desc)"
* )
* @Rest\QueryParam(
* name="limit",
* requirements="\d+",
* default="15",
* description="Max number of answers per page."
* )
* @Rest\QueryParam(
* name="offset",
* requirements="\d+",
* default="1",
* description="The pagination offset"
* )
* @Rest\View(StatusCode = 200, serializerGroups={"answer_list"})
*/
public function listAction(ParamFetcherInterface $paramFetcher)
{
$user = $this->getUser();
$pager = $this->getDoctrine()->getRepository('AppBundle:Answer')->search(
$paramFetcher->get('order'),
$paramFetcher->get('limit'),
$paramFetcher->get('offset'),
$user->getId()
);
return new Answers($pager);
}
/**
* @Rest\Post("/api/answers", name="api_answer_create")
* @Rest\View(StatusCode = 201)
*/
public function createAction(Request $request)
{
$usr = $this->getUser();
if ($usr !== null) {
$answer = new Answer($usr, null, 'SENDED');
$em = $this->getDoctrine()->getManager();
$mediaId = htmlspecialchars($request->get('mediaId'));
$companyId = htmlspecialchars($request->get('companyId'));
$adId = htmlspecialchars($request->get('adId'));
if (!is_numeric($mediaId) || !is_numeric($companyId) || ($adId != null && !is_numeric($adId))) {
$message = 'Le média, l\'entreprise ou l\'offre ne sont pas au format demandé';
$status = 'failure';
throw new ResourceValidationException($message, $status);
}
$existAdAnswer = null;
$existCompanyAnswer = null;
// Verify if users have already posted answers
if (isset($adId) && $adId != null) {
$existAdAnswer = $em->getRepository('AppBundle:Answer')->findOneBy(array('user' => $usr, 'ad' => $adId));
} else {
$existCompanyAnswer = $em->getRepository('AppBundle:Answer')->findOneBy(array('user' => $usr, 'company' => $companyId));
}
if (!isset($mediaId) || !isset($companyId) || $mediaId == null || $companyId == null) {
$message = 'Aucune vidéo ou entreprise sélectionnée.';
$status = 'failure';
throw new ResourceValidationException($message, $status);
} else if ($existAdAnswer) {
$message = 'Vous avez déja postulé pour cette offre';
$status = 'failure';
throw new ResourceValidationException($message, $status);
} else if ($existCompanyAnswer) {
$message = 'Vous avez déja postulé pour cette entreprise.';
$status = 'failure';
throw new ResourceValidationException($message, $status);
} else {
$video = $em->getRepository('AppBundle:Media')->find($mediaId);
$company = $em->getRepository('AppBundle:Company')->find($companyId);
// Verify if company or video exists
if (!$video || !$company) {
$message = 'Pas d\'entreprises ou de vidéos existantes';
$status = 'failure';
throw new ResourceValidationException($message, $status);
}
if (isset($adId) && $adId != null) {
$ad = $em->getRepository('AppBundle:Ad')->find($adId);
$answer->setAd($ad);
}
$answer ->setVideo($video)
->setCompany($company)
->setSendTime(new \DateTime());
$em->persist($answer);
$em->flush();
$userCompany = $company->getUsers();
/*$message = new Message('Candidature', 'Video', $usr, $userCompany{
0}, 'CONTACT_TALENT', $answer);
$message->setVideo($video);
$em->persist($message);
$em->flush();*/
$status = array('status' => "success", "idAnswer" => $answer->getId()/*, "idMessage" => $message->getId()*/);
}
} else {
$message = 'Vous n\'êtes pas connecté en tant qu\'utilisateur.';
}
return new JsonResponse($status);
}
// valid request (from postman code ):
//POST /app_dev.php/api/media HTTP/1.1
// Host: localhost
// Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
// Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpYXQiOjE1NTg2MTM2NzYsImV4cCI6MTU1ODYxNzI3Niwicm9sZXMiOlsiUk9MRV9UQUxFTlQiLCJST0xFX1VTRVIiXSwidXNlcm5hbWUiOiJ0aG9tYXMuYmVycm9kQGUtZGVjbGljLmNvbSJ9.gREC7Haj2geQNn3WArAL4jhBcPI67YJuJOEYiTJ4VeJztM7TRKo8XplXXdDKRs-J_AsHIOmEYWb08AZIivNXw652Ge_9VhpvhS67xa2O30T-ZingVVofZ8Anjbgof32tVkwL2SzNd82rxw4DbFWgSE24h1tw2NO-EUnvLxD3eGUgPerdJ-g74zwJ4tv2kBI3_TaTR35x0HjPnxtihpT2FQHwR-kYQHtJb7rmR7XTloDBu-cZiiEkfgZekt2NyOvD58HcXy3hKZ09YvIFmwDnmVxOVvexVPPt8du-ozXqtt6IlXGslqTm_dX7eTNrg2uoKgliBV6AOYFFlylgIQU1-Wr6k_OCxDEscN3NkbTDVcQbE-xSE2wjFIO0Gilk-cpmW5Kx1VCtEtyscPRiYub6dXPBgObGdKGmTcYwlG3X03x9KO9oYmjVgIreZZg2WJTzwQOoU67QxhOYknPshBSm61-VaB9OwOGJG3M6FrhZR867-Rj64FEd0HWH9lMM5OO645hlDAe3lPCG6ffUBPBOjFWCGx8HPsv_PjOaMRf21UEFpVaTfAlHrKsUog5j8Qc5-OEz9vmmlog2KjWc67alEfJujnc0m3HV731IBirar5gaO360ebwUU6aSo6HSThOnwFrTxGiCd0Eqo5T5yW446HJBRhLFYiiJerJg6EbGlAM
// User-Agent: PostmanRuntime/7.13.0
// Accept: */*
// Cache-Control: no-cache
// Postman-Token: 49a92aa5-fa39-412c-bc23-9d6ae389fa1e,569d0fea-09ba-452f-9957-989fca193603
// Host: localhost
// accept-encoding: gzip, deflate
// content-length: 228
// Connection: keep-alive
// cache-control: no-cache
// Content-Disposition: form-data; name="upload"; filename="/C:/Users/Thomas/Pictures/Camera Roll/WIN_20180917_14_29_28_Pro.mp4
// ------WebKitFormBoundary7MA4YWxkTrZu0gW--
/**
* @Rest\Post("/api/media", name="api_media_upload")
* @Rest\View(StatusCode = 201)
*
*/
public function uploadAction(Request $request)
{
$usr = $this->get('security.token_storage')->getToken()->getUser();
$usr->getUsername();
$file = $request->files->get('upload');
$status = array('status' => "success", "fileUploaded" => false);
//dump($file);
// If a file was uploaded
if (!is_null($file)) {
$mediaManager = $this->get('media_manager');
$message = $mediaManager->upload(null, $file, $usr);
//dump($message);
// generate a random name for the file but keep the extension
// $filename = uniqid().".".$file->getClientOriginalExtension();
// $path = "/path/where/we/want-to-save-the-file";
// $file->move($path,$filename); // move the file to a path
$status = array('status' => "success", "fileUploaded" => true, "message" => $message);
}
return new JsonResponse($status);
}
/**
* @Rest\Post("/api/answers/message", name="api_answer_message")
* @Rest\View(StatusCode = 201)
*/
public function addMessageAction(Request $request)
{
$usr = $this->get('security.token_storage')->getToken()->getUser();
$usr->getUsername();
$em = $this->getDoctrine()->getManager();
$answerId = htmlspecialchars($request->get('answerId'));
$messageText = htmlspecialchars($request->get('message'));
$existAnswer = $em->getRepository('AppBundle:Answer')->findOneBy(array('id' => $answerId));
if (!isset($existAnswer)) {
$message = 'Aucune candidature ne correspond.';
$status = 'failure';
throw new ResourceValidationException($message, $status);
}
if (empty($messageText)) {
$message = 'Le message est vide.';
$status = 'failure';
throw new ResourceValidationException($message, $status);
}
$answerReceipiant = $existAnswer->getAd() !== null ? $existAnswer->getAd()->getCreator()
: $existAnswer->getCompany()->getUsers(){ 0 };
$message = new message('Chat', $messageText, $this->getUser(), $answerReceipiant, 'Message du talent', $existAnswer);
$em->persist($message);
$em->flush();
$status = array('status' => "success");
return new JsonResponse($status);
}
/**
* @Rest\Get("/api/answers/{id}/messages", name="api_answer_messages", requirements={"id"="\d+"})
* @Rest\View(StatusCode = 200, serializerGroups={"answer_detail"})
*/
public function fetchMessageAction(Answer $answer)
{
$em = $this->getDoctrine()->getManager();
$usr = $this->get('security.token_storage')->getToken()->getUser();
if ($answer->getUser()->getId() !== $usr->getId()) {
$message = "vous n'avez pas le droit de voir ce message.";
$status = 'failure';
throw new ResourceValidationException($message, $status);
}
$messages = $em->getRepository('AppBundle:Message')->searchCorrespondences($answer);
//
$status = array('status' => "success", "messages" => $messages);
//
$data = $this->get('jms_serializer')->serialize(
$status,
'json',
SerializationContext::create()->setGroups(array('answer_detail'))
);
return new JsonResponse($data, 200, [], true);
}
}
@@ -0,0 +1,116 @@
<?php
namespace AppBundle\Controller\Api;
use AppBundle\Entity\Company;
use AppBundle\Representation\Companies;
use AppBundle\Representation\SingleCompany;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Controller\Annotations\Get;
use FOS\RestBundle\Controller\Annotations\Post;
use FOS\RestBundle\Controller\Annotations\View;
use FOS\RestBundle\Controller\FOSRestController;
use FOS\RestBundle\Request\ParamFetcherInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use JMS\Serializer\SerializationContext;
use Symfony\Component\HttpFoundation\JsonResponse;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class CompanyController extends FOSRestController
{
/**
* @Rest\Get(path="/api/companies/{id}", name="api_company_show", requirements={"id"="\d+"})
* @Rest\View
*/
public function showAction(Company $company)
{
$data = $this->get('jms_serializer')->serialize($company, 'json', SerializationContext::create()->setGroups(array('company_detail')));
return new JsonResponse($data, 200, [], true);
}
/**
* @Rest\Get("/api/companies", name="api_company_list")
* @Rest\QueryParam(
* name="keyword",
* requirements="[a-zA-Z -@$']+",
* nullable=true,
* description="The keyword to search for."
* )
* @Rest\QueryParam(
* name="order",
* requirements="asc|desc",
* default="asc",
* description="Sort order (asc or desc)"
* )
* @Rest\QueryParam(
* name="limit",
* requirements="\d+",
* default="10",
* nullable=true,
* description="Max number of companies per page."
* )
* @Rest\QueryParam(
* name="offset",
* requirements="\d+",
* nullable=true,
* default="1",
* description="The pagination offset"
* )
* @Rest\QueryParam(
* name="isEmphasis",
* requirements="\d+",
* nullable=true,
* description="Companies are promoted -mise en avant"
* )
* @Rest\View(statusCode=200, serializerGroups={"company_list"})
*/
public function listAction(ParamFetcherInterface $paramFetcher)
{
$pager = $this->getDoctrine()->getRepository('AppBundle:Company')->search(
$paramFetcher->get('keyword'),
$paramFetcher->get('order'),
$paramFetcher->get('limit'),
$paramFetcher->get('offset'),
$paramFetcher->get('isEmphasis')
);
return new Companies($pager);
}
/**
* @Rest\Post("/api/companies", name="api_company_create")
* @Rest\View(StatusCode = 201)
* @ParamConverter("company", converter="fos_rest.request_body")
*/
public function createAction(Company $company)
{
$em = $this->getDoctrine()->getManager();
$em->persist($company);
$em->flush();
return $this->view(
new SingleCompany($company),
Response::HTTP_CREATED,
['Location' => $this->generateUrl('api_company_show', ['id' => $company->getId(), UrlGeneratorInterface::ABSOLUTE_URL])]);
}
/**
* @Rest\Get(path="/api/companyAjaxRecStat/{id}", name="companyAjaxRecStat", requirements={"id"="\d+"})
* @Rest\View(statusCode=200)
*/
public function companyAjaxRecStatAction(Company $company)
{
$history = $this->get('edeclic.history.record');
if ($this->getUser() && $this->getUser()->getCompany() != null) {
if ($this->getUser()->getCompany()->getId() !== $company->getId()) {
$history->recordIt($this->getUser()->getId(), "r", get_class($company), $company->getId(), serialize($company));
}
} else {
$history->recordIt("Anonymous", "r", 'AppBundle\Entity\Company', $company->getId(), serialize($company));
}
return new JsonResponse(array('code' => "ok"));
}
}
@@ -0,0 +1,137 @@
<?php
/*
* This file is part of the FOSRestBundle package.
*
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace AppBundle\Controller\Api;
use FOS\RestBundle\Util\ExceptionValueMap;
use FOS\RestBundle\View\View;
use FOS\RestBundle\View\ViewHandlerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Debug\Exception\FlattenException;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
/**
* Custom ExceptionController that uses the view layer and supports HTTP response status code mapping.
*/
class ExceptionController
{
/**
* @var ViewHandlerInterface
*/
private $viewHandler;
/**
* @var ExceptionValueMap
*/
private $exceptionCodes;
/**
* @var bool
*/
private $showException;
public function __construct(
ViewHandlerInterface $viewHandler,
ExceptionValueMap $exceptionCodes,
$showException
) {
$this->viewHandler = $viewHandler;
$this->exceptionCodes = $exceptionCodes;
$this->showException = $showException;
}
/**
* Converts an Exception to a Response.
*
* @param Request $request
* @param \Exception|\Throwable $exception
* @param DebugLoggerInterface|null $logger
*
* @throws \InvalidArgumentException
*
* @return Response
*/
public function showAction(Request $request, $exception, DebugLoggerInterface $logger = null)
{
$currentContent = $this->getAndCleanOutputBuffering($request->headers->get('X-Php-Ob-Level', -1));
$code = $this->getStatusCode($exception);
$templateData = $this->getTemplateData($currentContent, $code, $exception, $logger);
$view = $this->createView($exception, $code, $templateData, $request, $this->showException);
$response = $this->viewHandler->handle($view);
return $response;
}
/**
* @param \Exception $exception
* @param int $code
* @param array $templateData
* @param Request $request
* @param bool $showException
*
* @return View
*/
protected function createView(\Exception $exception, $code, array $templateData, Request $request, $showException)
{
$view = new View($exception, $code, $exception instanceof HttpExceptionInterface ? $exception->getHeaders() : []);
$view->setTemplateVar('raw_exception');
$view->setTemplateData($templateData);
return $view;
}
/**
* Determines the status code to use for the response.
*
* @param \Exception $exception
*
* @return int
*/
protected function getStatusCode(\Exception $exception)
{
// If matched
if ($statusCode = $this->exceptionCodes->resolveException($exception)) {
return $statusCode;
}
// Otherwise, default
if ($exception instanceof HttpExceptionInterface) {
return $exception->getStatusCode();
}
return 500;
}
/**
* Determines the template parameters to pass to the view layer.
*
* @param string $currentContent
* @param int $code
* @param \Exception $exception
* @param DebugLoggerInterface $logger
*
* @return array
*/
private function getTemplateData($currentContent, $code, \Exception $exception, DebugLoggerInterface $logger = null)
{
return [
'exception' => FlattenException::create($exception),
'status' => 'error',
'status_code' => $code,
'status_text' => array_key_exists($code, Response::$statusTexts) ? Response::$statusTexts[$code] : 'error',
'currentContent' => $currentContent,
'logger' => $logger,
];
}
/**
* Gets and cleans any content that was already outputted.
*
* This code comes from Symfony and should be synchronized on a regular basis
* see src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php
*
* @return string
*/
private function getAndCleanOutputBuffering($startObLevel)
{
if (ob_get_level() <= $startObLevel) {
return '';
}
Response::closeOutputBuffers($startObLevel + 1, true);
return ob_get_clean();
}
}
@@ -0,0 +1,59 @@
<?php
namespace AppBundle\Controller\Api;
use AppBundle\Entity\User;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Controller\Annotations\Get;
use FOS\RestBundle\Controller\Annotations\Post;
use FOS\RestBundle\Controller\Annotations\View;
use FOS\RestBundle\Controller\FOSRestController;
use FOS\RestBundle\Request\ParamFetcherInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use JMS\Serializer\SerializationContext;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpFoundation\Request;
class PushController extends FOSRestController
{
/**
* @Rest\Get("/api/userSubscriptionToPush", name="getUserSubscriptionToPush")
* @Rest\View(statusCode=200)
*/
public function getUserSubscriptionToPush()
{
$user = $this->getUser();
$managerPush = $this->get('app.user_subscription_manager');
$isUserSubscribed = ($managerPush->findByUser($user))? true : false;
return new JsonResponse(array('isUserSubscribed' => $isUserSubscribed));
}
/**
* @Rest\Post("/api/userSubscriptionToPush", name="postUserSubscriptionToPush")
* @Rest\View(statusCode=200)
*/
public function saveSubscription(Request $request)
{
$user = $this->getUser();
$subscription = json_decode($request->getContent(), true);
if (JSON_ERROR_NONE !== json_last_error()) {
throw new BadRequestHttpException(json_last_error_msg());
}
if (!isset($subscription['endpoint'])) {
throw new BadRequestHttpException('Invalid subscription object.');
}
$manager = $this->container->get("app.user_subscription_manager");
$subscriptionHash = $manager->hash($subscription['endpoint']);
$userSubscription = $manager->getUserSubscription($user, $subscriptionHash)
or $userSubscription = $manager->factory($user, $subscriptionHash, $subscription);
$manager->save($userSubscription);
return new JsonResponse(array('success' => true),200);
}
}
@@ -0,0 +1,586 @@
<?php
namespace AppBundle\Controller\Api;
use FOS\RestBundle\Controller\Annotations as Rest;
use FOS\RestBundle\Controller\Annotations\Post;
use FOS\RestBundle\Controller\Annotations\View;
use FOS\RestBundle\Controller\FOSRestController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use FOS\UserBundle\Model\UserManagerInterface;
use FOS\UserBundle\FOSUserEvents;
use FOS\UserBundle\Event\GetResponseUserEvent;
use FOS\UserBundle\Model\UserInterface;
use AppBundle\Entity\Company;
use AppBundle\Exception\ResourceValidationException;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use AppBundle\Form\ContactTalentType;
use AppBundle\Form\MediaType;
use AppBundle\Form\TalentProfileType;
use AppBundle\Form\TalentType;
use AppBundle\Form\CareersType;
use AppBundle\Form\FormationsType;
use AppBundle\Form\LanguagesType;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
class SecurityController extends FOSRestController
{
/**
* @Rest\Post(path="/api/confirmAccount", name="api_confirm_account")
* @Rest\View
*/
public function ConfirmAccount(Request $request)
{
$userManager = $this->get('fos_user.user_manager');
$email = $request->get('email');
$confirmationToken = $request->get('confirmationToken');
if (!isset($email) || !isset($confirmationToken))
$status = array('status' => "failure", 'message' => "Paramètres invalides.");
else {
$user = $userManager->findUserByConfirmationToken($confirmationToken);
if (isset($user)) {
if ($user->getEmail() !== $email)
$status = array('status' => "failure", 'message' => "Aucune confirmation effectuée. NB: Tentative de corruption !", "email" => $user->getEmail());
else {
$user->setConfirmationToken(null);
$user->setEnabled(true);
$userManager->updateUser($user);
$status = array('status' => "success");
}
} else {
$status = array('status' => "failure", 'message' => "Aucune confirmation effectuée.");
}
}
return new JsonResponse($status);
}
/**
* @Rest\Post(path="/api/register", name="api_register")
* @Rest\View
*/
public function Register(Request $request)
{
$firstname = htmlspecialchars($request->get('firstname'));
$lastname = htmlspecialchars($request->get('lastname'));
$email = htmlspecialchars($request->get('email'));
$password = htmlspecialchars($request->get('password'));
if (!isset($firstname) || !isset($lastname) || !isset($email) || !isset($password))
$status = array('status' => "failure", 'message' => 'empty parameters');
else {
$userManager = $this->get('fos_user.user_manager');
$user = $userManager->findUserByEmail($email);
if (isset($user))
$status = array('status' => "failure", 'message' => "L'utilisateur existe déjà.");
else {
$user = $userManager->createUser();
$user->setUsername($firstname . "-" . $lastname);
$user->setFirstname($firstname);
$user->setLastname($lastname);
$user->setEmail($email);
$user->setPlainPassword($password);
$user->setEnabled(false);
$user->setRoles(array('ROLE_TALENT'));
$tokengen = $this->get('fos_user.util.token_generator');
$user->setConfirmationToken($tokengen->generateToken());
$userManager->updateUser($user);
if ($user->getCompany() == null) {
$company = new Company();
$slugService = $this->get('mt.slug');
$alias = $slugService->slugify($user->getId() . "-" . $user->getFirstname() . "-" . $user->getLastname());
$company->setAlias($alias);
$company->setType("TALENT");
$user->setCompany($company);
$userManager->updateUser($user);
}
// $userManager->updatePassword($user);//pas besoin car fait dans updateUser , vraiment bizarre....
$status = array('status' => "success", 'confirmationToken' => $user->getConfirmationToken(), 'email' => $user->getEmail(), 'firstname' => $user->getFirstname(), 'lastname' => $user->getLastname());
}
}
return new JsonResponse($status);
}
/**
* @Rest\post(path="/api/update_user", name="api_update_user")
* @Rest\View
*/
public function UpdateUser(Request $request)
{
$companyManager = $this->get('app.company_manager');
$usr = $this->getUser();
$talent = $usr->getCompany();
if ($usr !== null){
$newLastName = htmlspecialchars($request->get('lastname'));
$newFirstName = htmlspecialchars($request->get('firstname'));
$phoneTalent = htmlspecialchars($request->get('phone'));
$titleTalent = htmlspecialchars($request->get('currentJob'));
$newLinkedin = htmlspecialchars($request->get('linkedin'));
$newTwitter = htmlspecialchars($request->get('twitter'));
$newWebsite = htmlspecialchars($request->get('website'));
if (!isset($newLastName) || !isset($newFirstName) || $newLastName == null || $newFirstName == null){
$message = 'Vous devez rentrer votre nom et votre prénom pour continuer';
throw new ResourceValidationException($message,'');
} else {
$usr->setLastName($newLastName);
$usr->setFirstName($newFirstName);
$talent->setWebsite($newWebsite);
$talent->setLinkedin($newLinkedin);
$talent->setTwitter($newTwitter);
$talent->setTitleTalent($titleTalent);
$talent->setPhoneTalent($phoneTalent);
$companyManager->updateTalent($usr);
$status = array('status' => "success");
}
} else {
$status = array('status' => "failure", 'message' => "Vous n'êtes pas connecté.");
}
return new JsonResponse($status);
}
/**
* @Rest\post(path="/api/update_profile_picture", name="api_update_profile_picture")
* @Rest\View
*/
public function UpdateProfilPicture(Request $request)
{
$userManager = $this->get('fos_user.user_manager');
$usr = $this->getUser();
if ($usr !== null){
$file = $request->files->get('file');
$usr->setFile($file);
$usr->upload();
$userManager->updateUser($usr);
$status = array('status' => "success", 'file' => $usr->getPhoto());
} else {
$status = array('status' => "failure", 'message' => "Vous n'êtes pas connecté.");
}
return new JsonResponse($status);
}
/**
* @Rest\post(path="/api/reset_password", name="reset_password")
* @Rest\View
*/
public function ResetPassword(Request $request)
{
$email = $request->request->get('username');
$user = $this->get('fos_user.user_manager')->findUserByEmail($email);
if (null === $user) {
throw $this->createNotFoundException();
}
if ($user->isPasswordRequestNonExpired($this->container->getParameter('fos_user.resetting.token_ttl'))) {
throw new ResourceValidationException('Password request allready requested', "failure", 500);
}
if (null === $user->getConfirmationToken()) {
/** @var $tokenGenerator \FOS\UserBundle\Util\TokenGeneratorInterface */
$tokenGenerator = $this->get('fos_user.util.token_generator');
$user->setConfirmationToken($tokenGenerator->generateToken());
}
$this->get('fos_user.mailer')->sendResettingEmailMessage($user);
$user->setPasswordRequestedAt(new \DateTime());
$this->get('fos_user.user_manager')->updateUser($user);
$status = array('status' => "success");
return new JsonResponse($status);
}
/**
* @Rest\get(path="/api/user", name="api_user")
* @Rest\View
*/
public function FetchUser(Request $request)
{
$usr = $this->getUser();
if ($usr !== null)
$status = array('status' => "success", 'user' => $usr->getIdCard());
else
$status = array('status' => "failure", 'user' => null);
return new JsonResponse($status);
}
/**
* @Rest\Post(path="/api/login_check_oauth", name="api_oauth_login")
* @Rest\View
*/
public function OAuthLoginAction(Request $request)
{
$jwtManager = $this->container->get('lexik_jwt_authentication.jwt_manager');
$token = $request->get('oauth-token');
$type = $request->get('oauth-type');
if ($type == "facebook") {
$user = $this->getOrCreateTTUserWithFacebookAccessToken($token);
} else if ($type == "linkedin") {
$user = $this->getOrCreateTTUserWithLinkedInAccessToken($token);
}
return new JsonResponse(['token' => $jwtManager->create($user)]);
}
private function getOrCreateTTUserWithFacebookAccessToken($token)
{
$em = $this->getDoctrine()->getManager();
//verify access token a facebook endpoint
// https://graph.facebook.com/debug_token?
// input_token=EAAhJAcmfVSoBAFESNEQPJFv4fOqY5G6pSUwU3BOVzmhfoP9DTu827RUelrUQHFJshZBHsHZAlZA22MvfZArsZAlJBvZBWgbuJAJQjbMcgr9dwtHZBWZCI61nsvSBbsjiA8RgonGu0zcMD8GZCJDoZA26fZAgmURRgJUprfZCOvEzZBFgfUo1UjIHhiqey&access_token=2332071840142634|afb8bbca72bd8c517c64f81e998e4f12
//TODO: à mettre en config
$req = 'https://graph.facebook.com/debug_token?input_token=' . ($token) . '&access_token=1800752833559014|454de729b1e58f506f94c8b50ca5c011';//PROD PREPROD
//'&access_token=2332071840142634|afb8bbca72bd8c517c64f81e998e4f12'; //DEV
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $req,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => array(
"Accept: */*",
"Cache-Control: no-cache",
"Connection: keep-alive",
"Host: graph.facebook.com",
// "Postman-Token: a81ddeb6-2c8c-462a-ae2d-958821c48ed2,04c50334-5c3c-4a1e-a988-d613ddd06656",
// "User-Agent: PostmanRuntime/7.13.0",
"accept-encoding: gzip, deflate",
"cache-control: no-cache"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
//dump($response);
if ($err) {
//TODO:
// dump("cURL Error #:" . $err);
}
$data = json_decode($response);
//dump($data);
//dump($data->data->user_id);
//retreive user in our database
$user = $em->getRepository('AppBundle:User')->findOneByFacebookId($data->data->user_id);
if ($user === null) {
//try find one by tenants email
$user = $this->findUserWithFacebookEmailAndAttach($data->data, $token);
//create new user
if ($user === null) {
$user = $this->createTTUserFromOauth($data->data, 'facebook', $token);
}
}
//TODO: catch
//dump($user);
return $user;
}
private function getOrCreateTTUserWithLinkedInAccessToken($token)
{
$em = $this->getDoctrine()->getManager();
//$req = 'https://api.linkedin.com/v1/people/~:(id,email-address,first-name,last-name,headline,picture-url,location,industry,current-share,num-connections,summary,specialties,positions)?format=json&oauth2_access_token=' . ($token);
//dump($req);
$reqMe = 'https://api.linkedin.com/v2/me?oauth2_access_token=' . $token;
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $reqMe,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => array(
"Accept: */*",
"Cache-Control: no-cache",
"Connection: keep-alive",
"Host: api.linkedin.com",
"User-Agent: PostmanRuntime/7.15.0",
"accept-encoding: gzip, deflate",
"cache-control: no-cache",
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
//TODO: log ??
//dump("cURL Error #:" . $err);
}
$data = json_decode($response);
//dump($data);
//dump($data->data->user_id);
//retreive user in our database
$user = $em->getRepository('AppBundle:User')->findOneByLinkedinId($data->id);
if ($user === null) {
$email = $this->requestLinkedInEmail($token);
$data->emailAddress = $email;
//try find one by tenants email and attach it
$user = $this->findUserWithLinkedInEmailAndAttach($data);
//create a new user
if ($user === null)
$user = $this->createTTUserFromOauth($data, 'linkedin',$token);
}
//TODO : catch
return $user;
}
private function requestLinkedInEmail($token)
{
$reqEmail = 'https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))&oauth2_access_token=' . $token;
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $reqEmail,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => array(
"Accept: */*",
"Cache-Control: no-cache",
"Connection: keep-alive",
"Host: api.linkedin.com",
"User-Agent: PostmanRuntime/7.15.0",
"accept-encoding: gzip, deflate",
"cache-control: no-cache",
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
//TODO: log ??
//dump("cURL Error #:" . $err);
}
$data = json_decode($response);
return $data->elements[0]->{'handle~'}->emailAddress;
}
private function findUserWithLinkedInEmailAndAttach($data)
{
$userManager = $this->get('fos_user.user_manager');
if (isset($data->emailAddress))
$userEmail = $data->emailAddress;
else
return null;
$user = $userManager->findUserByEmail($userEmail);
if($user == null)
return null;
$user->setLinkedinId($data->id);
$userManager->updateUser($user);
return $user;
}
private function findUserWithFacebookEmailAndAttach($data, $user_access_token)
{
$userManager = $this->get('fos_user.user_manager');
$profile = $this->getFacebookProfile($data->user_id, $user_access_token);
if (isset($profile->email)) {
$userEmail = $profile->email;
} else {
$userEmail = null;
return null;
}
$user = $userManager->findUserByEmail($userEmail);
if($user == null)
return null;
$user->setFacebookId($data->user_id);
$userManager->updateUser($user);
return $user;
}
private function createTTUserFromOauth($data, $tenant, $token)
{
$userManager = $this->get('fos_user.user_manager');
if ($tenant == 'facebook') {
$profile = $this->getFacebookProfile($data->user_id, $token);
//TODO : photo facebook
// $userPhoto = 'https://graph.facebook.com/' . $data->user_id . '/picture?height=200'. '&access_token=2332071840142634|afb8bbca72bd8c517c64f81e998e4f12';
$userPhoto='';
if (isset($profile->birthday)) {
$birthday = \DateTime::createFromFormat('m/d/Y', $profile->birthday);
} else {
$birthday = null;
}
if (isset($profile->gender)) {
$gender = $profile->gender;
} else {
$gender = null;
}
if (isset($profile->email)) {
$userEmail = $profile->email;
} else {
$userEmail = null;
}
$id = $profile->id;
$firstname = $profile->first_name;
$lastname = $profile->last_name;
}
if ($tenant == 'linkedin') {
//TODO
$id = $data->id;
$birthday = null;
$gender = null;
if (isset($data->pictureUrl)) {
$userPhoto = $data->pictureUrl;
} else {
$userPhoto = null;
}
$userEmail = $data->emailAddress;
$firstname = $data->localizedFirstName;
$lastname = $data->localizedLastName;
}
$user = $userManager->createUser();
$user->setUsername($firstname . "-" . $lastname);
$user->setFirstname($firstname);
$user->setLastname($lastname);
$user->setEmail($userEmail);
$user->setPlainPassword(uniqid());
$user->setEnabled(true);
$user->setSocialPicture($userPhoto);
$user->setRoles(array('ROLE_TALENT'));
$user->setBirthday($birthday);
$user->setGender($gender);
if ($tenant == "linkedin") {
$user->setLinkedinId($id);
}
if ($tenant == "facebook") {
$user->setFacebookId($id);
}
$userManager->updateUser($user);
if ($user->getCompany() == null) {
$company = new Company();
$slugService = $this->get('mt.slug');
$alias = $slugService->slugify($user->getId() . "-" . $user->getFirstname() . "-" . $user->getLastname());
$company->setAlias($alias);
$company->setType("TALENT");
$user->setCompany($company);
$userManager->updateUser($user);
}
$token = new UsernamePasswordToken($user, null, "main", $user->getRoles());
$this->container->get("security.token_storage")->setToken($token);
return $user;
}
private function getFacebookProfile($user_id, $user_access_token)
{
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://graph.facebook.com/" . $user_id . "?fields=id,name,gender,birthday,first_name,last_name,email" . "&access_token=" . $user_access_token,
// '&access_token=1800752833559014|454de729b1e58f506f94c8b50ca5c011',//PROD PREPROD
// "&access_token=2332071840142634|afb8bbca72bd8c517c64f81e998e4f12", //DEV
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => array(
"Accept: */*",
"Cache-Control: no-cache",
"Connection: keep-alive",
"Host: graph.facebook.com",
//"Postman-Token: e0ab326f-4916-4c8b-80a1-bd082ce6e6a2,f972ce2f-f209-4f60-84cd-e04099e8e43d",
"User-Agent: PostmanRuntime/7.13.0",
"accept-encoding: gzip, deflate",
"cache-control: no-cache"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
//echo $response;
}
$data = json_decode($response);
return $data;
}
/**
* @Rest\Get(path="/api/talent", name="api_talent")
* @Rest\View
*/
public function goToMonCompte(Request $request)
{
$user = $this->getUser();
$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
$this->get('security.token_storage')->setToken($token);
$this->get('session')->set('_security_main', serialize($token));
$event = new InteractiveLoginEvent($request, $token);
$this->get("event_dispatcher")->dispatch("security.interactive_login", $event);
$view = $this->redirectView($this->generateUrl('talent_dashboard'), 301);
return $this->handleView($view);
}
}
@@ -187,7 +187,13 @@ class CompanyController extends Controller
$history->recordIt("Anonymous", "r", 'AppBundle\Entity\Company', $company->getId(), serialize($company));
}
return new JsonResponse(array('code' => "ok"));
if(!$this->getUser() == null){
return new JsonResponse(array('code' => "ok", "user" => $this->getUser()->getUsername()));
} else{
return new JsonResponse(array('code' => "ok"));
}
}
/***********************
@@ -1,11 +1,9 @@
<?php
namespace AppBundle\Controller;
use AppBundle\Form\AdSearchType;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class DefaultController extends Controller
{
/**
@@ -19,7 +17,7 @@ class DefaultController extends Controller
$ads = $em->getRepository('AppBundle:Ad')->findBy(array("status" => "PUBLISHED", "isPromoted" => false), array('id' => 'DESC'));
}
$talents = $em->getRepository('AppBundle:Company')->findBy(array("type" => "TALENT", "emphasis" => true), array('emphasisOrder' => 'DESC'));
$companies = $em->getRepository('AppBundle:Company')->findBy(array("type" => "COMPANY", "emphasis" => true), array('emphasisOrder' => 'ASC'));
$companies = $em->getRepository('AppBundle:Company')->findBy(array("type" => "COMPANY", "emphasis" => true), array('emphasisOrder' => 'DESC'));
$territories = $em->getRepository('AppBundle:Company')->findBy(array("type" => "TERRITORY", "emphasis" => true), array('emphasisOrder' => 'ASC'));
$arrayTalents = array();
@@ -62,6 +60,60 @@ class DefaultController extends Controller
);
}
/**
* @Route("/indexv2", name="homepagev2")
*/
public function homepagev2Action()
{
$em = $this->getDoctrine()->getManager();
$ads = $em->getRepository('AppBundle:Ad')->findBy(array("status" => "PUBLISHED", "emphasis" => true, "isPromoted" => false), array('emphasisOrder' => 'DESC'));
if (!$ads) {
$ads = $em->getRepository('AppBundle:Ad')->findBy(array("status" => "PUBLISHED", "isPromoted" => false), array('id' => 'DESC'));
}
$talents = $em->getRepository('AppBundle:Company')->findBy(array("type" => "TALENT", "emphasis" => true), array('emphasisOrder' => 'DESC'));
$companies = $em->getRepository('AppBundle:Company')->findBy(array("type" => "COMPANY", "emphasis" => true), array('emphasisOrder' => 'DESC'));
$territories = $em->getRepository('AppBundle:Company')->findBy(array("type" => "TERRITORY", "emphasis" => true), array('emphasisOrder' => 'ASC'));
$arrayTalents = array();
foreach ($talents as $talent) {
if ($talent->getPresentationVideo()) {
$arrayTalents[] = $talent;
}
}
$arrayCompany = array();
foreach ($companies as $company) {
if ($company->getPresentationVideo()) {
$arrayCompany[] = $company;
}
}
$mediaManager = $this->get('media_manager');
foreach ($ads as $ad) {
$mediaManager->getThumbnails($ad);
}
foreach ($companies as $company) {
$mediaManager->getThumbnails($company);
}
foreach ($territories as $t) {
$mediaManager->getThumbnails($t);
}
$form = $this->createForm(AdSearchType::class);
return $this->render(
'defaultv2/accueil/index.html.twig', [
'ads' => $ads,
'companies' => $arrayCompany,
'talents' => $arrayTalents,
'territories' => $territories,
'searchform' => $form->createView(),
]
);
}
/**
* @Route("/redirect_dashboard", name="redirect_dashboard")
*/
@@ -98,4 +150,5 @@ class DefaultController extends Controller
//return $this->render('page_static/video_territoire.html.twig');
return $this->render('page_static/accompagnement_video_territoire.html.twig');
}
}
@@ -0,0 +1,74 @@
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use BenTools\WebPushBundle\Registry\WebPushManagerRegistry;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Security\Core\User\UserInterface;
class PushController extends Controller
{
/**
* @Route("/push/save-subscription/", name="save-subscription")
*/
public function saveSubscription(Request $request)
{
//Sample Request
// {
// "endpoint":"https://fcm.googleapis.com/fcm/send/cUugkgI46DE:APA91bEUZ-AN2BfyEmxNilWKdg1qUZObgQ1Q_T1cWxM2ECqdH00AyXYt1R4snPkX12s4-38_LWF3Yrx6xcXYna0lUsL9ImBTrxjJHzv9SLTXrJI4f0omqf285fOZ8oeo50jqKB6rNiOF",
// "expirationTime":null,
// "keys":{
// "p256dh":"BPprM2eUBJR85AkTlYaryaByeF3TKYEJ-VyZcdgx51SyijfyLgohFYK0fM9HZoAUIwwUx-_LtthqNGZDVxcx-uo",
// "auth":"YtUnqHo0RTsBn7B_BaFT8Q"}
// }
$user = $this->getUser();
// if (!$user) {
// throw new BadRequestHttpException("User is not logged in.");
// }
$subscription = json_decode($request->getContent(), true);
if (JSON_ERROR_NONE !== json_last_error()) {
throw new BadRequestHttpException(json_last_error_msg());
}
if (!isset($subscription['endpoint'])) {
throw new BadRequestHttpException('Invalid subscription object.');
}
// if (!$user instanceof UserInterface) {
// throw new \RuntimeException('This bundle only works with user object that implement ' . UserInterface::class);
// }
$manager = $this->container->get("app.user_subscription_manager");
$subscriptionHash = $manager->hash($subscription['endpoint']);
$userSubscription = $manager->getUserSubscription($user, $subscriptionHash)
or $userSubscription = $manager->factory($user, $subscriptionHash, $subscription);
$manager->save($userSubscription);
return new JsonResponse(array('success' => true),200);
}
/**
* @Route("/push/delete-subscription/", name="delete-subscription")
*/
public function unsubscribeUser(Request $request)
{
$subscription = json_decode($request->getContent(), true);
if (JSON_ERROR_NONE !== json_last_error()) {
throw new BadRequestHttpException(json_last_error_msg());
}
if (!isset($subscription['endpoint'])) {
throw new BadRequestHttpException('Invalid subscription object.');
}
$manager = $this->container->get("app.user_subscription_manager");
$subscriptionHash = $manager->hash($subscription['endpoint']);
$userSubscription = $this->manager->findByHash($subscriptionHash);
if(!empty($userSubscription))
$manager->delete($userSubscription[0]);
return new JsonResponse(array('success' => true),200);
}
}
@@ -174,17 +174,52 @@ class TalentController extends Controller
{
$userManager = $this->get('fos_user.user_manager');
$user = $this->getUser();
$formFactory = $this->container->get('fos_user.change_password.form.factory');
$formPw = $formFactory->createForm();
$formPw->setData($user);
if ($formPw->isSubmitted() && $formPw->isValid()) {
$userManager->updateUser($user);
}
$manager = $this->container->get("app.user_subscription_manager");
$subscriptions = $manager->findByUser($user);
$isNotificationAllowed = !empty($subscriptions);
return $this->render('talent/my_account.html.twig', [
'formPw' => $formPw->createView(),
'isNotificationAllowed' => $isNotificationAllowed
]);
}
/**
* @Route("/talent/me/notificationConsent", name="talent_notification_consent")
*/
public function notificationConsent(Request $request)
{
$data = json_decode($request->getContent(), true);
$consent = $data["notificationConsent"];
if($consent === false)
{
//delete all existing user_subscription
$user = $this->getUser();
$manager = $this->container->get("app.user_subscription_manager");
$subscriptions = $manager->findByUser($user);
foreach ($subscriptions as $key => $value) {
$manager->delete($value);
}
}
$encode = array('notificationConsent' => $consent);
return new JsonResponse(json_encode($encode));
}
/**
* @Route("/talent/me/espace-oe", name="talent_ad_space")
*/
@@ -8,6 +8,11 @@ use AppBundle\Utils\Traits\StatusTrait;
use AppBundle\Utils\Traits\TimestampableTrait;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use JMS\Serializer\Annotation\ExclusionPolicy;
use JMS\Serializer\Annotation\Expose;
use JMS\Serializer\Annotation\Groups;
use JMS\Serializer\Annotation\Type;
use Hateoas\Configuration\Annotation as Hateoas;
/**
* Ad
@@ -15,6 +20,26 @@ use Symfony\Component\Validator\Constraints as Assert;
* @ORM\Table(name="ad")
* @ORM\Entity(repositoryClass="AppBundle\Repository\AdRepository")
* @ORM\HasLifecycleCallbacks()
*
*
* @Hateoas\Relation(
* "self",
* href = @Hateoas\Route(
* "api_ad_show",
* parameters = { "id" = "expr(object.getId())" },
* absolute=true
* )
* )
*
* @Hateoas\Relation(
* "company",
* embedded = @Hateoas\Embedded("expr(object.getCompany())")
* )
*
* @Hateoas\Relation(
* "creator",
* embedded = @Hateoas\Embedded("expr(object.getCreator())")
* )
*/
class Ad
{
@@ -30,6 +55,9 @@ class Ad
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*
* @Groups({"ad_detail" , "ad_list", "company_detail", "answer_list", "answer_detail"})
* @Type("integer")
*/
private $id;
@@ -37,6 +65,7 @@ class Ad
* @var string
*
* @ORM\Column(name="reference", type="string", length=255)
*
*/
private $reference;
@@ -51,6 +80,8 @@ class Ad
* @var string
*
* @ORM\Column(name="title", type="string", length=255)
*
* @Groups({"ad_detail" , "ad_list", "company_detail", "answer_list", "answer_detail"})
*/
private $title;
@@ -65,6 +96,8 @@ class Ad
* @var string
*
* @ORM\Column(name="description", type="text", nullable=true)
*
* @Groups({"ad_detail", "answer_detail"})
*/
private $description;
@@ -94,6 +127,8 @@ class Ad
* @var boolean
*
* @ORM\Column(name="is_promoted", type="boolean", nullable=true, options={"comment":"Peux t'on répondre"})
*
* @Groups({"ad_detail" ,"company_detail", "ad_list"})
*/
private $isPromoted;
@@ -108,6 +143,7 @@ class Ad
* @var boolean
*
* @ORM\Column(name="is_answerable", type="boolean", nullable=true, options={"comment":"Annonce promu ?"})
* @Groups({"company_detail"})
*/
private $isAnswerable;
@@ -115,6 +151,7 @@ class Ad
* @var integer
*
* @ORM\Column(name="defcon", type="smallint", nullable=true, options={"comment":"Etat d'alerte de modération"})
*
*/
private $defcon;
@@ -122,6 +159,8 @@ class Ad
* @var array
*
* @ORM\Column(name="public_tag", type="json_document", nullable=true, options={"jsonb":true})
*
* @Groups({"ad_detail", "answer_detail"})
*/
private $publicTag;
@@ -136,6 +175,9 @@ class Ad
* @var array
*
* @ORM\Column(name="extra", type="json_document", nullable=true, options={"jsonb":true})
*
* @Groups({"ad_detail", "ad_list", "answer_detail", "company_detail"})
*
*/
private $extra;
@@ -143,21 +185,29 @@ class Ad
* @var array
*
* @ORM\Column(name="location", type="json_document", nullable=true, options={"jsonb":true})
*
* @Groups({"ad_detail", "ad_list","answer_detail", "company_detail"})
*/
private $location;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Media", inversedBy="ads", cascade={"persist"})
*
* @Groups({"ad_detail", "ad_list", "company_detail", "answer_list", "answer_detail"})
*
*/
private $video;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Company", inversedBy="ads")
*
* @Groups({"ad_detail" , "ad_list", "company_detail", "answer_list", "answer_detail"})
*/
private $company;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="ads")
*
*/
private $creator;
@@ -165,6 +215,8 @@ class Ad
* @var string
*
* @ORM\Column(name="emphasis", type="boolean", options={"comment":"A la une"}, nullable=true)
*
* @Groups({"company_list"})
*/
private $emphasis;
@@ -197,11 +249,14 @@ class Ad
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\TerritoryAd", mappedBy="ad", cascade={"persist", "remove"})
*
* @Groups({"ad_detail" , "answer_detail"})
*/
private $territories;
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\BookmarkAd", mappedBy="ad", cascade={"persist", "remove"})
*
*/
private $bookmarkAds;
@@ -7,6 +7,11 @@ use AppBundle\Utils\Traits\StatusTrait;
use AppBundle\Utils\Traits\TimestampableTrait;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Criteria as Criteria;
use JMS\Serializer\Annotation\ExclusionPolicy;
use JMS\Serializer\Annotation\Expose;
use Hateoas\Configuration\Annotation as Hateoas;
use JMS\Serializer\Annotation\Groups;
use JMS\Serializer\Annotation\Accessor;
/**
* Answer
@@ -14,6 +19,32 @@ use Doctrine\Common\Collections\Criteria as Criteria;
* @ORM\Table(name="answer")
* @ORM\Entity(repositoryClass="AppBundle\Repository\AnswerRepository")
* @ORM\HasLifecycleCallbacks()
*
*
*
* @Hateoas\Relation(
* "self",
* href = @Hateoas\Route(
* "api_answer_show",
* parameters = { "id" = "expr(object.getId())" },
* absolute=true
* )
* )
*
* @Hateoas\Relation(
* "ad",
* embedded = @Hateoas\Embedded("expr(object.getAd())")
* )
*
* @Hateoas\Relation(
* "user",
* embedded = @Hateoas\Embedded("expr(object.getUser())")
* )
*
* @Hateoas\Relation(
* "company",
* embedded = @Hateoas\Embedded("expr(object.getCompany())")
* )
*/
class Answer
{
@@ -28,28 +59,34 @@ class Answer
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @Groups({"answer_list", "answer_detail"})
*
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Ad", inversedBy="answers")
* @ORM\JoinColumn(nullable=true)
* @Groups({"answer_list", "answer_detail"})
*/
private $ad;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Company", inversedBy="spontaneousApplications")
* @ORM\JoinColumn(nullable=true)
* @Groups({"answer_list", "answer_detail"})
*/
private $company;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="answers", cascade={"persist"})
* @Groups({"answer_list", "answer_detail"})
*/
private $user;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Media", inversedBy="answers", cascade={"persist"})
* @Groups({"answer_list", "answer_detail"})
*/
private $video;
@@ -57,6 +94,7 @@ class Answer
* @var int
*
* @ORM\Column(name="vote", type="smallint", nullable=true)
*
*/
private $vote;
@@ -64,6 +102,7 @@ class Answer
* @var string
*
* @ORM\Column(name="comment", type="text", nullable=true)
* @Groups({"answer_detail","answer_list"})
*/
private $comment;
@@ -71,6 +110,7 @@ class Answer
* @var \DateTime $sendTime
*
* @ORM\Column(name="send_time", type="datetime", nullable=true)
* @Groups({"answer_detail","answer_list"})
*/
private $sendTime;
@@ -86,6 +126,7 @@ class Answer
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Message", mappedBy="answer", cascade={"persist", "remove"})
* @ORM\OrderBy({"uTime" = "DESC"})
* @Groups({"answer_detail","answer_list"})
*/
private $messages;
@@ -136,7 +177,7 @@ class Answer
$criteria = Criteria::create()
->where(Criteria::expr()->neq('status', "DRAFT"));
return $this->messages->matching($criteria)->last();
return $this->messages->matching($criteria)->first();
}
public function getIsViewed(){
@@ -38,7 +38,7 @@ class BookmarkAd
private $bookmark;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Ad")
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Ad" , inversedBy="bookmarkAds")
*/
private $ad;
@@ -8,7 +8,13 @@ use AppBundle\Utils\Traits\IsVisibleTrait;
use AppBundle\Utils\Traits\TagsJsonTrait;
use AppBundle\Utils\Traits\TimestampableTrait;
use Doctrine\ORM\Mapping as ORM;
use Hateoas\Configuration\Annotation as Hateoas;
use JMS\Serializer\Annotation\ExclusionPolicy;
use JMS\Serializer\Annotation\Expose;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use JMS\Serializer\Annotation\Groups;
use JMS\Serializer\Annotation\Accessor;
use JMS\Serializer\Annotation\Type;
/**
* Company
@@ -16,6 +22,17 @@ use Symfony\Component\HttpFoundation\File\UploadedFile;
* @ORM\Table(name="company")
* @ORM\Entity(repositoryClass="AppBundle\Repository\CompanyRepository")
* @ORM\HasLifecycleCallbacks()
*
*
* @Hateoas\Relation(
* "self",
* href = @Hateoas\Route(
* "api_company_show",
* parameters = { "id" = "expr(object.getId())" },
* absolute=true
* )
* )
*
*/
class Company
{
@@ -32,6 +49,9 @@ class Company
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*
* @Groups({ "ad_detail", "company_list", "company_detail", "answer_list"})
* @Type("integer")
*/
private $id;
@@ -39,6 +59,8 @@ class Company
* @var string
*
* @ORM\Column(name="brand_name", type="string", length=255, options={"comment":"Nom commercial"}, nullable=true)
*
* @Groups({"ad_detail", "ad_list", "company_list", "company_detail","answer_detail","answer_list"})
*/
private $brandName;
@@ -46,6 +68,9 @@ class Company
* @var string
*
* @ORM\Column(name="business_name", type="string", length=255, options={"comment":"Raison sociale"}, nullable=true)
*
* @Groups({"ad_detail", "ad_list", "company_list", "company_detail","answer_detail","answer_list"})
*
*/
private $businessName;
@@ -53,6 +78,7 @@ class Company
* @var text
*
* @ORM\Column(name="description", type="text", length=255, nullable=true)
* @Groups({"company_detail"})
*/
private $description;
@@ -67,6 +93,8 @@ class Company
* @var string
*
* @ORM\Column(name="logo", type="string", nullable=true)
*
* @Groups({"ad_detail", "ad_list", "company_list", "company_detail", "answer_detail","answer_list"})
*/
private $logo;
@@ -74,6 +102,8 @@ class Company
* @var string
*
* @ORM\Column(name="website", type="string", nullable=true)
*
* @Groups({"company_detail"})
*/
private $website;
@@ -87,6 +117,7 @@ class Company
/**
* @ORM\OneToOne(targetEntity="AppBundle\Entity\Media", cascade={"persist", "remove"})
* @ORM\JoinColumn(name="presentation_video_id", nullable=true)
* @Groups({"ad_detail", "company_detail", "company_list","answer_detail","answer_list"})
*/
private $presentationVideo;
@@ -143,6 +174,7 @@ class Company
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Ad",mappedBy="company", cascade={"persist", "remove"})
* @Groups({"company_detail", "company_list"})
*/
private $ads;
@@ -153,14 +185,25 @@ class Company
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\TerritoryAd", mappedBy="company", cascade={"persist", "remove"})
* @Groups({"company_detail"})
*/
private $territories;
/**
* @ORM\OneToMany(targetEntity="AppBundle\Entity\Answer",mappedBy="company", cascade={"persist", "remove"})
*
* @Groups({"company_detail", "company_list"})
*/
private $spontaneousApplications;
/**
* @Groups({"company_detail", "company_list"})
* @Accessor(getter="getCountPublishedAds")
*
* @Groups({"ad_list", "company_list", "company_detail"})
*/
private $countAds;
/***********************
* Constructor
***********************/
@@ -277,6 +320,46 @@ class Company
return $this->users->first();
}
/**
* @return int
*
* Return a percentage
*/
public function getCompanyCompleteness()
{
$total=9;
$empty=0;
if (empty($this->brandName))
$empty++;
if (empty($this->businessName))
$empty++;
if (empty($this->description))
$empty++;
if (empty($this->logo))
$empty++;
if (empty($this->website))
$empty++;
if (empty($this->alias))
$empty++;
if (empty($this->publicTag))
$empty++;
if ($this->presentationVideo == null)
$empty++;
if (is_array($this->ad) && empty($this->ad))
$empty++;
return ($empty/$total) * 100;
}
/***********************
* Getter & Setters
***********************/
@@ -834,4 +917,16 @@ class Company
{
return $this->isPrivate;
}
/**
* Get countAds.
*
* @return int|null
*/
public function getCountPublishedAds()
{
return count($this->getPublishedAds());
}
}
@@ -6,6 +6,7 @@ use AppBundle\Utils\Traits\IsVisibleTrait;
use AppBundle\Utils\Traits\ModerationTrait;
use AppBundle\Utils\Traits\StatusTrait;
use AppBundle\Utils\Traits\TimestampableTrait;
use JMS\Serializer\Annotation\Groups;
use Doctrine\ORM\Mapping as ORM;
/**
@@ -29,6 +30,9 @@ class Media
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*
* @Groups({"ad_detail", "company_list", "answer_detail"})
*
*/
private $id;
@@ -36,6 +40,8 @@ class Media
* @var string
*
* @ORM\Column(name="title", type="string", length=255)
* @Groups({"ad_detail", "answer_detail"})
*
*/
private $title;
@@ -50,6 +56,8 @@ class Media
* @var string
*
* @ORM\Column(name="cdn_url", type="string", length=255)
*
* @Groups({"ad_detail", "company_detail", "company_list", "answer_detail"})
*/
private $cdnUrl;
@@ -57,6 +65,7 @@ class Media
* @var string
*
* @ORM\Column(name="metadata", type="text")
*
*/
private $metadata;
@@ -78,6 +87,8 @@ class Media
* @var array
*
* @ORM\Column(name="thumbnails", type="json_document", nullable=true)
*
* @Groups({"ad_detail", "ad_list", "company_list", "company_detail", "answer_list"})
*/
private $thumbnails;
@@ -4,6 +4,7 @@ namespace AppBundle\Entity;
use AppBundle\Utils\Traits\StatusTrait;
use AppBundle\Utils\Traits\TimestampableTrait;
use JMS\Serializer\Annotation\Groups;
use Doctrine\ORM\Mapping as ORM;
/**
@@ -24,6 +25,7 @@ class Message
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @Groups({"answer_detail","answer_list"})
*/
private $id;
@@ -31,6 +33,7 @@ class Message
* @var string
*
* @ORM\Column(name="subject", type="text")
* @Groups({"answer_detail","answer_list"})
*/
private $subject;
@@ -38,16 +41,19 @@ class Message
* @var string
*
* @ORM\Column(name="content", type="text")
* @Groups({"answer_list","answer_detail","answer_list"})
*/
private $content;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="sendedMessages", cascade={"persist"})
* @Groups({"answer_list","answer_detail","answer_list"})
*/
private $sender;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\User", inversedBy="receivedMessages", cascade={"persist"})
* @Groups({"answer_detail","answer_list"})
*/
private $recipient;
@@ -59,6 +65,7 @@ class Message
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Media", inversedBy="answers", cascade={"persist"})
* @Groups({"answer_list", "answer_detail"})
*/
private $video;
@@ -4,6 +4,7 @@ namespace AppBundle\Entity;
use AppBundle\Utils\Traits\StatusTrait;
use AppBundle\Utils\Traits\TimestampableTrait;
use JMS\Serializer\Annotation\Groups;
use Doctrine\ORM\Mapping as ORM;
/**
@@ -7,6 +7,8 @@ use AppBundle\Utils\Traits\StatusTrait;
use AppBundle\Utils\Traits\TimestampableTrait;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation\Groups;
/**
* Recommendation
*

Some files were not shown because too many files have changed in this diff Show More