From 3e7a9522b666c699b3c878766ba6fe1bab1b5982 Mon Sep 17 00:00:00 2001 From: nobohan Date: Wed, 14 Jul 2021 11:45:13 +0200 Subject: [PATCH 01/59] init Calendar bundle --- composer.json | 3 +- src/Bundle/ChillCalendarBundle/.gitignore | 11 + .../ChillCalendarBundle.php | 9 + src/Bundle/ChillCalendarBundle/LICENSE | 661 ++++++++++++++++++ src/Bundle/ChillCalendarBundle/README.md | 6 + src/Bundle/ChillCalendarBundle/composer.json | 30 + 6 files changed, 719 insertions(+), 1 deletion(-) create mode 100644 src/Bundle/ChillCalendarBundle/.gitignore create mode 100644 src/Bundle/ChillCalendarBundle/ChillCalendarBundle.php create mode 100644 src/Bundle/ChillCalendarBundle/LICENSE create mode 100644 src/Bundle/ChillCalendarBundle/README.md create mode 100644 src/Bundle/ChillCalendarBundle/composer.json diff --git a/composer.json b/composer.json index f5f1a2806..fb8c9c333 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,8 @@ "Chill\\TaskBundle\\": "src/Bundle/ChillTaskBundle", "Chill\\ThirdPartyBundle\\": "src/Bundle/ChillThirdPartyBundle", "Chill\\AsideActivityBundle\\": "src/Bundle/ChillAsideActivityBundle/src", - "Chill\\DocGeneratorBundle\\": "src/Bundle/ChillDocGeneratorBundle" + "Chill\\DocGeneratorBundle\\": "src/Bundle/ChillDocGeneratorBundle", + "Chill\\CalendarBundle\\": "src/Bundle/ChillCalendarBundle" } }, "autoload-dev": { diff --git a/src/Bundle/ChillCalendarBundle/.gitignore b/src/Bundle/ChillCalendarBundle/.gitignore new file mode 100644 index 000000000..f443cb81e --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/.gitignore @@ -0,0 +1,11 @@ +composer.lock +vendor/* +parameters.yml +*~ +*.DS_Store +*.sass-cache +Resources/node_modules/ +Tests/Fixtures/App/app/config/parameters.yml +/nbproject/private/ +Resources/test/Fixtures/App/bootstrap.php.cache + diff --git a/src/Bundle/ChillCalendarBundle/ChillCalendarBundle.php b/src/Bundle/ChillCalendarBundle/ChillCalendarBundle.php new file mode 100644 index 000000000..cfbfa5b38 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/ChillCalendarBundle.php @@ -0,0 +1,9 @@ + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. \ No newline at end of file diff --git a/src/Bundle/ChillCalendarBundle/README.md b/src/Bundle/ChillCalendarBundle/README.md new file mode 100644 index 000000000..538a7ffa7 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/README.md @@ -0,0 +1,6 @@ +Calendar bundle +=============== + +This bundle adds a calendar to chill. + + diff --git a/src/Bundle/ChillCalendarBundle/composer.json b/src/Bundle/ChillCalendarBundle/composer.json new file mode 100644 index 000000000..fc96ea04b --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/composer.json @@ -0,0 +1,30 @@ +{ + "name": "chill-project/calendar", + "description": "This bundle extends chill for managing a calendar", + "type": "symfony-bundle", + "license": "AGPL-3.0-or-later", + "keywords" : ["chill", "social work"], + "homepage" : "hhttps://gitlab.com/Chill-Projet/chill-bundles/", + "autoload": { + "psr-4": { "Chill\\CalendarBundle\\": "" } + }, + "autoload-dev": { + "classmap": [ "Resources/test/Fixtures/App/app/AppKernel.php" ] + }, + "authors": [ + { + "name": "Champs-Libres", + "email": "info@champs-libres.coop" + } + ], + "require": { + }, + "require-dev": { + }, + "extra": { + "app-migrations-dir": "Resources/test/Fixtures/App/app/DoctrineMigrations", + "symfony-app-dir": "Test/Fixtures/App/app/" + }, + "minimum-stability": "dev", + "prefer-stable": true +} From 3010df2016d0192dd030efad2965f91cc63cb213 Mon Sep 17 00:00:00 2001 From: nobohan Date: Thu, 15 Jul 2021 15:57:10 +0200 Subject: [PATCH 02/59] calendar: add entities --- .../ChillCalendarBundle/Entity/Calendar.php | 367 ++++++++++++++++++ .../Entity/CalendarRange.php | 81 ++++ .../Entity/CancelReason.php | 76 ++++ .../ChillCalendarBundle/Entity/Invite.php | 60 +++ .../Repository/CalendarRangeRepository.php | 50 +++ .../Repository/CalendarRepository.php | 50 +++ .../Repository/CancelReasonRepository.php | 50 +++ .../Repository/InviteRepository.php | 50 +++ 8 files changed, 784 insertions(+) create mode 100644 src/Bundle/ChillCalendarBundle/Entity/Calendar.php create mode 100644 src/Bundle/ChillCalendarBundle/Entity/CalendarRange.php create mode 100644 src/Bundle/ChillCalendarBundle/Entity/CancelReason.php create mode 100644 src/Bundle/ChillCalendarBundle/Entity/Invite.php create mode 100644 src/Bundle/ChillCalendarBundle/Repository/CalendarRangeRepository.php create mode 100644 src/Bundle/ChillCalendarBundle/Repository/CalendarRepository.php create mode 100644 src/Bundle/ChillCalendarBundle/Repository/CancelReasonRepository.php create mode 100644 src/Bundle/ChillCalendarBundle/Repository/InviteRepository.php diff --git a/src/Bundle/ChillCalendarBundle/Entity/Calendar.php b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php new file mode 100644 index 000000000..226a78634 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php @@ -0,0 +1,367 @@ +comment = new CommentEmbeddable(); + $this->persons = new ArrayCollection(); + $this->nonProfessionals = new ArrayCollection(); + $this->professionals = new ArrayCollection(); + $this->invites = new ArrayCollection(); + } + + + public function getId(): ?int + { + return $this->id; + } + + public function getSendSMS(): ?bool + { + return $this->sendSMS; + } + + public function setSendSMS(?bool $sendSMS): self + { + $this->sendSMS = $sendSMS; + + return $this; + } + + public function getComment(): CommentEmbeddable + { + return $this->comment; + } + + public function setComment(CommentEmbeddable $comment): self + { + $this->comment = $comment; + + return $this; + } + + public function getStartDate(): ?\DateTimeImmutable + { + return $this->startDate; + } + + public function setStartDate(\DateTimeImmutable $startDate): self + { + $this->startDate = $startDate; + + return $this; + } + + public function getEndDate(): ?\DateTimeImmutable + { + return $this->endDate; + } + + public function setEndDate(\DateTimeImmutable $endDate): self + { + $this->endDate = $endDate; + + return $this; + } + + public function getStatus(): ?string + { + return $this->status; + } + + public function setStatus(string $status): self + { + $this->status = $status; + + return $this; + } + + public function getUser(): ?User + { + return $this->user; + } + + public function setUser(?User $user): self + { + $this->user = $user; + + return $this; + } + + public function getAccompanyingPeriod(): ?AccompanyingPeriod + { + return $this->accompanyingPeriod; + } + + public function setAccompanyingPeriod(?AccompanyingPeriod $accompanyingPeriod): self + { + $this->accompanyingPeriod = $accompanyingPeriod; + + return $this; + } + + public function getMainUser(): ?User + { + return $this->mainUser; + } + + public function setMainUser(?User $mainUser): self + { + $this->mainUser = $mainUser; + + return $this; + } + + /** + * @return Collection|Person[] + */ + public function getPersons(): Collection + { + return $this->persons; + } + + public function addPerson(Person $person): self + { + if (!$this->persons->contains($person)) { + $this->persons[] = $person; + } + + return $this; + } + + public function removePerson(Person $person): self + { + $this->persons->removeElement($person); + + return $this; + } + + /** + * @return Collection|Person[] + */ + public function getNonProfessionals(): Collection + { + return $this->nonProfessionals; + } + + public function addNonProfessional(Person $nonProfessional): self + { + if (!$this->nonProfessionals->contains($nonProfessional)) { + $this->nonProfessionals[] = $nonProfessional; + } + + return $this; + } + + public function removeNonProfessional(Person $nonProfessional): self + { + $this->nonProfessionals->removeElement($nonProfessional); + + return $this; + } + + /** + * @return Collection|ThirdParty[] + */ + public function getProfessionals(): Collection + { + return $this->professionals; + } + + public function addProfessional(ThirdParty $professional): self + { + if (!$this->professionals->contains($professional)) { + $this->professionals[] = $professional; + } + + return $this; + } + + public function removeProfessional(ThirdParty $professional): self + { + $this->professionals->removeElement($professional); + + return $this; + } + + /** + * @return Collection|Invite[] + */ + public function getInvites(): Collection + { + return $this->invites; + } + + public function addInvite(Invite $invite): self + { + if (!$this->invites->contains($invite)) { + $this->invites[] = $invite; + } + + return $this; + } + + public function removeInvite(Invite $invite): self + { + $this->invites->removeElement($invite); + + return $this; + } + + public function getCancelReason(): ?CancelReason + { + return $this->cancelReason; + } + + public function setCancelReason(?CancelReason $cancelReason): self + { + $this->cancelReason = $cancelReason; + + return $this; + } + + public function getCalendarRange(): ?CalendarRange + { + return $this->calendarRange; + } + + public function setCalendarRange(?CalendarRange $calendarRange): self + { + $this->calendarRange = $calendarRange; + + return $this; + } + + public function getActivity(): ?Activity + { + return $this->activity; + } + + public function setActivity(?Activity $activity): self + { + $this->activity = $activity; + + return $this; + } +} diff --git a/src/Bundle/ChillCalendarBundle/Entity/CalendarRange.php b/src/Bundle/ChillCalendarBundle/Entity/CalendarRange.php new file mode 100644 index 000000000..62c1e943f --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Entity/CalendarRange.php @@ -0,0 +1,81 @@ +id; + } + + public function getStartDate(): ?\DateTimeImmutable + { + return $this->startDate; + } + + public function setStartDate(\DateTimeImmutable $startDate): self + { + $this->startDate = $startDate; + + return $this; + } + + public function getEndDate(): ?\DateTimeImmutable + { + return $this->endDate; + } + + public function setEndDate(\DateTimeImmutable $endDate): self + { + $this->endDate = $endDate; + + return $this; + } + + public function getUser(): ?User + { + return $this->user; + } + + public function setUser(?User $user): self + { + $this->user = $user; + + return $this; + } + + +} diff --git a/src/Bundle/ChillCalendarBundle/Entity/CancelReason.php b/src/Bundle/ChillCalendarBundle/Entity/CancelReason.php new file mode 100644 index 000000000..dacb2fd5e --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Entity/CancelReason.php @@ -0,0 +1,76 @@ +id; + } + + public function getActive(): ?bool + { + return $this->active; + } + + public function setActive(bool $active): self + { + $this->active = $active; + + return $this; + } + + public function getCanceledBy(): ?string + { + return $this->canceledBy; + } + + public function setCanceledBy(string $canceledBy): self + { + $this->canceledBy = $canceledBy; + + return $this; + } + + public function getName(): ?array + { + return $this->name; + } + + public function setName(array $name): self + { + $this->name = $name; + + return $this; + } +} diff --git a/src/Bundle/ChillCalendarBundle/Entity/Invite.php b/src/Bundle/ChillCalendarBundle/Entity/Invite.php new file mode 100644 index 000000000..b8ff4f1f5 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Entity/Invite.php @@ -0,0 +1,60 @@ +id; + } + + public function getStatus(): ?string + { + return $this->status; + } + + public function setStatus(string $status): self + { + $this->status = $status; + + return $this; + } + + public function getUser(): ?User + { + return $this->user; + } + + public function setUser(?User $user): self + { + $this->user = $user; + + return $this; + } +} diff --git a/src/Bundle/ChillCalendarBundle/Repository/CalendarRangeRepository.php b/src/Bundle/ChillCalendarBundle/Repository/CalendarRangeRepository.php new file mode 100644 index 000000000..a2c542436 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Repository/CalendarRangeRepository.php @@ -0,0 +1,50 @@ +createQueryBuilder('c') + ->andWhere('c.exampleField = :val') + ->setParameter('val', $value) + ->orderBy('c.id', 'ASC') + ->setMaxResults(10) + ->getQuery() + ->getResult() + ; + } + */ + + /* + public function findOneBySomeField($value): ?CalendarRange + { + return $this->createQueryBuilder('c') + ->andWhere('c.exampleField = :val') + ->setParameter('val', $value) + ->getQuery() + ->getOneOrNullResult() + ; + } + */ +} diff --git a/src/Bundle/ChillCalendarBundle/Repository/CalendarRepository.php b/src/Bundle/ChillCalendarBundle/Repository/CalendarRepository.php new file mode 100644 index 000000000..4f99c6d8e --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Repository/CalendarRepository.php @@ -0,0 +1,50 @@ +createQueryBuilder('c') + ->andWhere('c.exampleField = :val') + ->setParameter('val', $value) + ->orderBy('c.id', 'ASC') + ->setMaxResults(10) + ->getQuery() + ->getResult() + ; + } + */ + + /* + public function findOneBySomeField($value): ?Calendar + { + return $this->createQueryBuilder('c') + ->andWhere('c.exampleField = :val') + ->setParameter('val', $value) + ->getQuery() + ->getOneOrNullResult() + ; + } + */ +} diff --git a/src/Bundle/ChillCalendarBundle/Repository/CancelReasonRepository.php b/src/Bundle/ChillCalendarBundle/Repository/CancelReasonRepository.php new file mode 100644 index 000000000..11c2f7f59 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Repository/CancelReasonRepository.php @@ -0,0 +1,50 @@ +createQueryBuilder('c') + ->andWhere('c.exampleField = :val') + ->setParameter('val', $value) + ->orderBy('c.id', 'ASC') + ->setMaxResults(10) + ->getQuery() + ->getResult() + ; + } + */ + + /* + public function findOneBySomeField($value): ?CancelReason + { + return $this->createQueryBuilder('c') + ->andWhere('c.exampleField = :val') + ->setParameter('val', $value) + ->getQuery() + ->getOneOrNullResult() + ; + } + */ +} diff --git a/src/Bundle/ChillCalendarBundle/Repository/InviteRepository.php b/src/Bundle/ChillCalendarBundle/Repository/InviteRepository.php new file mode 100644 index 000000000..da9207cc4 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Repository/InviteRepository.php @@ -0,0 +1,50 @@ +createQueryBuilder('i') + ->andWhere('i.exampleField = :val') + ->setParameter('val', $value) + ->orderBy('i.id', 'ASC') + ->setMaxResults(10) + ->getQuery() + ->getResult() + ; + } + */ + + /* + public function findOneBySomeField($value): ?Invite + { + return $this->createQueryBuilder('i') + ->andWhere('i.exampleField = :val') + ->setParameter('val', $value) + ->getQuery() + ->getOneOrNullResult() + ; + } + */ +} From 38ec2b5de96ade67351caaabd58d06d2b5823a10 Mon Sep 17 00:00:00 2001 From: nobohan Date: Thu, 15 Jul 2021 16:16:08 +0200 Subject: [PATCH 03/59] rdv: correct entities with FQCN --- .../ChillCalendarBundle/Entity/Calendar.php | 16 ++++++++-------- .../ChillCalendarBundle/Entity/CalendarRange.php | 2 +- src/Bundle/ChillCalendarBundle/Entity/Invite.php | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Bundle/ChillCalendarBundle/Entity/Calendar.php b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php index 226a78634..9aacabcb1 100644 --- a/src/Bundle/ChillCalendarBundle/Entity/Calendar.php +++ b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php @@ -30,24 +30,24 @@ class Calendar private $id; /** - * @ORM\ManyToOne(targetEntity="User") + * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User") */ private User $user; /** - * @ORM\ManyToOne(targetEntity="AccompanyingPeriod") + * @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod") */ private AccompanyingPeriod $accompanyingPeriod; /** - * @ORM\ManyToOne(targetEntity="User") + * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User") */ private User $mainUser; /** * * @ORM\ManyToMany( - * targetEntity="Person", + * targetEntity="Chill\PersonBundle\Entity\Person", * cascade={"persist", "remove", "merge", "detach"}) * @ORM\JoinTable(name="chill_calendar.calendar_to_persons") */ @@ -56,16 +56,16 @@ class Calendar /** * * @ORM\ManyToMany( - * targetEntity="Person", + * targetEntity="Chill\PersonBundle\Entity\Person", * cascade={"persist", "remove", "merge", "detach"}) - * @ORM\JoinTable(name="chill_calendar.calendar_to_persons") + * @ORM\JoinTable(name="chill_calendar.calendar_to_non_professionals") */ private Collection $nonProfessionals; /** * * @ORM\ManyToMany( - * targetEntity="ThirdParty", + * targetEntity="Chill\ThirdPartyBundle\Entity\ThirdParty", * cascade={"persist", "remove", "merge", "detach"}) * @ORM\JoinTable(name="chill_calendar.calendar_to_thirdparties") */ @@ -113,7 +113,7 @@ class Calendar private ?CalendarRange $calendarRange = null; /** - * @ORM\ManyToOne(targetEntity="Activity") + * @ORM\ManyToOne(targetEntity="Chill\ActivityBundle\Entity\Activity") */ private Activity $activity; diff --git a/src/Bundle/ChillCalendarBundle/Entity/CalendarRange.php b/src/Bundle/ChillCalendarBundle/Entity/CalendarRange.php index 62c1e943f..6663d2ff9 100644 --- a/src/Bundle/ChillCalendarBundle/Entity/CalendarRange.php +++ b/src/Bundle/ChillCalendarBundle/Entity/CalendarRange.php @@ -20,7 +20,7 @@ class CalendarRange private $id; /** - * @ORM\ManyToOne(targetEntity="User") + * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User") */ private User $user; diff --git a/src/Bundle/ChillCalendarBundle/Entity/Invite.php b/src/Bundle/ChillCalendarBundle/Entity/Invite.php index b8ff4f1f5..c1f792d7d 100644 --- a/src/Bundle/ChillCalendarBundle/Entity/Invite.php +++ b/src/Bundle/ChillCalendarBundle/Entity/Invite.php @@ -20,7 +20,7 @@ class Invite private $id; /** - * @ORM\ManyToOne(targetEntity="User") + * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User") */ private User $user; From fdccdfe7b11826597aa637766fa2b67fd0ae9518 Mon Sep 17 00:00:00 2001 From: nobohan Date: Thu, 15 Jul 2021 16:25:13 +0200 Subject: [PATCH 04/59] rdv: add first migration --- .../migrations/Version20210715141731.php | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 src/Bundle/ChillCalendarBundle/migrations/Version20210715141731.php diff --git a/src/Bundle/ChillCalendarBundle/migrations/Version20210715141731.php b/src/Bundle/ChillCalendarBundle/migrations/Version20210715141731.php new file mode 100644 index 000000000..e93358fb7 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/migrations/Version20210715141731.php @@ -0,0 +1,96 @@ +addSql('CREATE SCHEMA chill_calendar'); + $this->addSql('CREATE SEQUENCE chill_calendar.calendar_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE SEQUENCE chill_calendar.calendar_range_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE SEQUENCE chill_calendar.cancel_reason_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE SEQUENCE chill_calendar.invite_id_seq INCREMENT BY 1 MINVALUE 1 START 1'); + $this->addSql('CREATE TABLE chill_calendar.calendar (id INT NOT NULL, user_id INT DEFAULT NULL, activity_id INT DEFAULT NULL, startDate DATE NOT NULL, endDate DATE NOT NULL, status VARCHAR(255) NOT NULL, sendSMS BOOLEAN DEFAULT NULL, comment_comment TEXT DEFAULT NULL, comment_userId INT DEFAULT NULL, comment_date TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, accompanyingPeriod_id INT DEFAULT NULL, mainUser_id INT DEFAULT NULL, cancelReason_id INT DEFAULT NULL, calendarRange_id INT DEFAULT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_712315ACA76ED395 ON chill_calendar.calendar (user_id)'); + $this->addSql('CREATE INDEX IDX_712315ACD7FA8EF0 ON chill_calendar.calendar (accompanyingPeriod_id)'); + $this->addSql('CREATE INDEX IDX_712315ACEFCB59C ON chill_calendar.calendar (mainUser_id)'); + $this->addSql('CREATE INDEX IDX_712315ACE980772F ON chill_calendar.calendar (cancelReason_id)'); + $this->addSql('CREATE INDEX IDX_712315ACC5CB285D ON chill_calendar.calendar (calendarRange_id)'); + $this->addSql('CREATE INDEX IDX_712315AC81C06096 ON chill_calendar.calendar (activity_id)'); + $this->addSql('COMMENT ON COLUMN chill_calendar.calendar.startDate IS \'(DC2Type:date_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_calendar.calendar.endDate IS \'(DC2Type:date_immutable)\''); + $this->addSql('CREATE TABLE chill_calendar.calendar_to_persons (calendar_id INT NOT NULL, person_id INT NOT NULL, PRIMARY KEY(calendar_id, person_id))'); + $this->addSql('CREATE INDEX IDX_AEE94715A40A2C8 ON chill_calendar.calendar_to_persons (calendar_id)'); + $this->addSql('CREATE INDEX IDX_AEE94715217BBB47 ON chill_calendar.calendar_to_persons (person_id)'); + $this->addSql('CREATE TABLE chill_calendar.calendar_to_non_professionals (calendar_id INT NOT NULL, person_id INT NOT NULL, PRIMARY KEY(calendar_id, person_id))'); + $this->addSql('CREATE INDEX IDX_FADF2C77A40A2C8 ON chill_calendar.calendar_to_non_professionals (calendar_id)'); + $this->addSql('CREATE INDEX IDX_FADF2C77217BBB47 ON chill_calendar.calendar_to_non_professionals (person_id)'); + $this->addSql('CREATE TABLE chill_calendar.calendar_to_thirdparties (calendar_id INT NOT NULL, thirdparty_id INT NOT NULL, PRIMARY KEY(calendar_id, thirdparty_id))'); + $this->addSql('CREATE INDEX IDX_2BAB7EFDA40A2C8 ON chill_calendar.calendar_to_thirdparties (calendar_id)'); + $this->addSql('CREATE INDEX IDX_2BAB7EFDC7D3A8E6 ON chill_calendar.calendar_to_thirdparties (thirdparty_id)'); + $this->addSql('CREATE TABLE chill_calendar.calendar_to_invites (calendar_id INT NOT NULL, invite_id INT NOT NULL, PRIMARY KEY(calendar_id, invite_id))'); + $this->addSql('CREATE INDEX IDX_FCBEAAAA40A2C8 ON chill_calendar.calendar_to_invites (calendar_id)'); + $this->addSql('CREATE INDEX IDX_FCBEAAAEA417747 ON chill_calendar.calendar_to_invites (invite_id)'); + $this->addSql('CREATE TABLE chill_calendar.calendar_range (id INT NOT NULL, user_id INT DEFAULT NULL, startDate DATE NOT NULL, endDate DATE NOT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_38D57D05A76ED395 ON chill_calendar.calendar_range (user_id)'); + $this->addSql('COMMENT ON COLUMN chill_calendar.calendar_range.startDate IS \'(DC2Type:date_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_calendar.calendar_range.endDate IS \'(DC2Type:date_immutable)\''); + $this->addSql('CREATE TABLE chill_calendar.cancel_reason (id INT NOT NULL, active BOOLEAN NOT NULL, canceledBy VARCHAR(255) NOT NULL, name JSON NOT NULL, PRIMARY KEY(id))'); + $this->addSql('COMMENT ON COLUMN chill_calendar.cancel_reason.name IS \'(DC2Type:json_array)\''); + $this->addSql('CREATE TABLE chill_calendar.invite (id INT NOT NULL, user_id INT DEFAULT NULL, status VARCHAR(255) NOT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE INDEX IDX_F517FFA7A76ED395 ON chill_calendar.invite (user_id)'); + $this->addSql('ALTER TABLE chill_calendar.calendar ADD CONSTRAINT FK_712315ACA76ED395 FOREIGN KEY (user_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_calendar.calendar ADD CONSTRAINT FK_712315ACD7FA8EF0 FOREIGN KEY (accompanyingPeriod_id) REFERENCES chill_person_accompanying_period (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_calendar.calendar ADD CONSTRAINT FK_712315ACEFCB59C FOREIGN KEY (mainUser_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_calendar.calendar ADD CONSTRAINT FK_712315ACE980772F FOREIGN KEY (cancelReason_id) REFERENCES chill_calendar.cancel_reason (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_calendar.calendar ADD CONSTRAINT FK_712315ACC5CB285D FOREIGN KEY (calendarRange_id) REFERENCES chill_calendar.calendar_range (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_calendar.calendar ADD CONSTRAINT FK_712315AC81C06096 FOREIGN KEY (activity_id) REFERENCES activity (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_calendar.calendar_to_persons ADD CONSTRAINT FK_AEE94715A40A2C8 FOREIGN KEY (calendar_id) REFERENCES chill_calendar.calendar (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_calendar.calendar_to_persons ADD CONSTRAINT FK_AEE94715217BBB47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_calendar.calendar_to_non_professionals ADD CONSTRAINT FK_FADF2C77A40A2C8 FOREIGN KEY (calendar_id) REFERENCES chill_calendar.calendar (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_calendar.calendar_to_non_professionals ADD CONSTRAINT FK_FADF2C77217BBB47 FOREIGN KEY (person_id) REFERENCES chill_person_person (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_calendar.calendar_to_thirdparties ADD CONSTRAINT FK_2BAB7EFDA40A2C8 FOREIGN KEY (calendar_id) REFERENCES chill_calendar.calendar (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_calendar.calendar_to_thirdparties ADD CONSTRAINT FK_2BAB7EFDC7D3A8E6 FOREIGN KEY (thirdparty_id) REFERENCES chill_3party.third_party (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_calendar.calendar_to_invites ADD CONSTRAINT FK_FCBEAAAA40A2C8 FOREIGN KEY (calendar_id) REFERENCES chill_calendar.calendar (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_calendar.calendar_to_invites ADD CONSTRAINT FK_FCBEAAAEA417747 FOREIGN KEY (invite_id) REFERENCES chill_calendar.invite (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_calendar.calendar_range ADD CONSTRAINT FK_38D57D05A76ED395 FOREIGN KEY (user_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + $this->addSql('ALTER TABLE chill_calendar.invite ADD CONSTRAINT FK_F517FFA7A76ED395 FOREIGN KEY (user_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE chill_calendar.calendar_to_persons DROP CONSTRAINT FK_AEE94715A40A2C8'); + $this->addSql('ALTER TABLE chill_calendar.calendar_to_non_professionals DROP CONSTRAINT FK_FADF2C77A40A2C8'); + $this->addSql('ALTER TABLE chill_calendar.calendar_to_thirdparties DROP CONSTRAINT FK_2BAB7EFDA40A2C8'); + $this->addSql('ALTER TABLE chill_calendar.calendar_to_invites DROP CONSTRAINT FK_FCBEAAAA40A2C8'); + $this->addSql('ALTER TABLE chill_calendar.calendar DROP CONSTRAINT FK_712315ACC5CB285D'); + $this->addSql('ALTER TABLE chill_calendar.calendar DROP CONSTRAINT FK_712315ACE980772F'); + $this->addSql('ALTER TABLE chill_calendar.calendar_to_invites DROP CONSTRAINT FK_FCBEAAAEA417747'); + $this->addSql('DROP SEQUENCE chill_calendar.calendar_id_seq CASCADE'); + $this->addSql('DROP SEQUENCE chill_calendar.calendar_range_id_seq CASCADE'); + $this->addSql('DROP SEQUENCE chill_calendar.cancel_reason_id_seq CASCADE'); + $this->addSql('DROP SEQUENCE chill_calendar.invite_id_seq CASCADE'); + $this->addSql('DROP TABLE chill_calendar.calendar'); + $this->addSql('DROP TABLE chill_calendar.calendar_to_persons'); + $this->addSql('DROP TABLE chill_calendar.calendar_to_non_professionals'); + $this->addSql('DROP TABLE chill_calendar.calendar_to_thirdparties'); + $this->addSql('DROP TABLE chill_calendar.calendar_to_invites'); + $this->addSql('DROP TABLE chill_calendar.calendar_range'); + $this->addSql('DROP TABLE chill_calendar.cancel_reason'); + $this->addSql('DROP TABLE chill_calendar.invite'); + } +} From 75caf3fa14193fb7afec7910517da3179ec5e4f1 Mon Sep 17 00:00:00 2001 From: nobohan Date: Fri, 16 Jul 2021 09:55:07 +0200 Subject: [PATCH 05/59] rdv: adapt entities + add fixtures --- .../Controller/CalendarController.php | 480 ++++++++++++++++++ .../DataFixtures/ORM/LoadCancelReason.php | 46 ++ .../DataFixtures/ORM/LoadInvite.php | 44 ++ .../ChillCalendarExtension.php | 48 ++ .../DependencyInjection/Configuration.php | 29 ++ .../Entity/CancelReason.php | 6 +- .../ChillCalendarBundle/Entity/Invite.php | 8 +- .../config/services/fixtures.yaml | 8 + .../migrations/Version20210715141731.php | 9 +- 9 files changed, 668 insertions(+), 10 deletions(-) create mode 100644 src/Bundle/ChillCalendarBundle/Controller/CalendarController.php create mode 100644 src/Bundle/ChillCalendarBundle/DataFixtures/ORM/LoadCancelReason.php create mode 100644 src/Bundle/ChillCalendarBundle/DataFixtures/ORM/LoadInvite.php create mode 100644 src/Bundle/ChillCalendarBundle/DependencyInjection/ChillCalendarExtension.php create mode 100644 src/Bundle/ChillCalendarBundle/DependencyInjection/Configuration.php create mode 100644 src/Bundle/ChillCalendarBundle/config/services/fixtures.yaml diff --git a/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php b/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php new file mode 100644 index 000000000..616829f19 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php @@ -0,0 +1,480 @@ +, + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace Chill\CalendarBundle\Controller; + +use Chill\MainBundle\Security\Authorization\AuthorizationHelper; +use Chill\PersonBundle\Entity\AccompanyingPeriod; +use Chill\PersonBundle\Entity\Person; +use Chill\PersonBundle\Privacy\PrivacyEvent; +use Psr\Log\LoggerInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\Form\Form; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; +use Symfony\Component\Form\Extension\Core\Type\SubmitType; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Core\Role\Role; +use Chill\CalendarBundle\Entity\Calendar; +use Chill\CalendarBundle\Form\CalendarType; +use Symfony\Component\Serializer\SerializerInterface; + +/** + * Class CalendarController + * + * @package Chill\CalendarBundle\Controller + */ +class CalendarController extends AbstractController +{ + protected EventDispatcherInterface $eventDispatcher; + + protected AuthorizationHelper $authorizationHelper; + + protected LoggerInterface $logger; + + protected SerializerInterface $serializer; + + public function __construct( + EventDispatcherInterface $eventDispatcher, + AuthorizationHelper $authorizationHelper, + LoggerInterface $logger, + SerializerInterface $serializer + ) { + $this->eventDispatcher = $eventDispatcher; + $this->authorizationHelper = $authorizationHelper; + $this->logger = $logger; + $this->serializer = $serializer; + } + + /** + * Lists all Calendar entities. + */ + public function listAction(Request $request): Response + { + $em = $this->getDoctrine()->getManager(); + $view = null; + + [$person, $accompanyingPeriod] = $this->getEntity($request); + + if ($person instanceof Person) { + $reachableScopes = $this->authorizationHelper + ->getReachableCircles($this->getUser(), new Role('CHILL_Calendar_SEE'), + $person->getCenter()); + + $activities = $em->getRepository(Calendar::class) + ->findByPersonImplied($person, $reachableScopes) + ; + + $event = new PrivacyEvent($person, array( + 'element_class' => Calendar::class, + 'action' => 'list' + )); + $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); + + $view = 'ChillCalendarBundle:Calendar:listPerson.html.twig'; + } elseif ($accompanyingPeriod instanceof AccompanyingPeriod) { + $activities = $em->getRepository('ChillCalendarBundle:Calendar')->findBy( + ['accompanyingPeriod' => $accompanyingPeriod], + ['date' => 'DESC'], + ); + + $view = 'ChillCalendarBundle:Calendar:listAccompanyingCourse.html.twig'; + } + + return $this->render($view, array( + 'activities' => $activities, + 'person' => $person, + 'accompanyingCourse' => $accompanyingPeriod, + )); + } + + public function selectTypeAction(Request $request): Response + { + $em = $this->getDoctrine()->getManager(); + $view = null; + + [$person, $accompanyingPeriod] = $this->getEntity($request); + + if ($accompanyingPeriod instanceof AccompanyingPeriod) { + $view = 'ChillCalendarBundle:Calendar:selectTypeAccompanyingCourse.html.twig'; + } elseif ($person instanceof Person) { + $view = 'ChillCalendarBundle:Calendar:selectTypePerson.html.twig'; + } + + $data = []; + + $activityTypeCategories = $em->getRepository(\Chill\CalendarBundle\Entity\ActivityTypeCategory::class) + ->findBy(['active' => true], ['ordering' => 'ASC']); + + foreach ($activityTypeCategories as $activityTypeCategory) { + $activityTypes = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityType::class) + ->findBy(['active' => true, 'category' => $activityTypeCategory], ['ordering' => 'ASC']); + + $data[] = [ + 'activityTypeCategory' => $activityTypeCategory, + 'activityTypes' => $activityTypes, + ]; + } + + if ($view === null) { + throw $this->createNotFoundException('Template not found'); + } + + return $this->render($view, [ + 'person' => $person, + 'accompanyingCourse' => $accompanyingPeriod, + 'data' => $data, + ]); + } + + public function newAction(Request $request): Response + { + $em = $this->getDoctrine()->getManager(); + + [$person, $accompanyingPeriod] = $this->getEntity($request); + + if ($accompanyingPeriod instanceof AccompanyingPeriod) { + $view = 'ChillCalendarBundle:Calendar:newAccompanyingCourse.html.twig'; + } elseif ($person instanceof Person) { + $view = 'ChillCalendarBundle:Calendar:newPerson.html.twig'; + } + + $activityType_id = $request->get('activityType_id', 0); + $activityType = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityType::class) + ->find($activityType_id); + + if (!$activityType instanceof \Chill\ActivityBundle\Entity\ActivityType || + !$activityType->isActive()) { + + $params = $this->buildParamsToUrl($person, $accompanyingPeriod); + return $this->redirectToRoute('chill_activity_activity_select_type', $params); + } + + $entity = new Calendar(); + $entity->setUser($this->getUser()); + + if ($person instanceof Person) { + $entity->setPerson($person); + } + + if ($accompanyingPeriod instanceof AccompanyingPeriod) { + $entity->setAccompanyingPeriod($accompanyingPeriod); + } + + $entity->setType($activityType); + $entity->setDate(new \DateTime('now')); + + // TODO revoir le Voter de Activity pour tenir compte qu'une activité peut appartenir a une période + // $this->denyAccessUnlessGranted('CHILL_ACTIVITY_CREATE', $entity); + + $form = $this->createForm(ActivityType::class, $entity, [ + 'center' => $entity->getCenter(), + 'role' => new Role('CHILL_ACTIVITY_CREATE'), + 'activityType' => $entity->getType(), + 'accompanyingPeriod' => $accompanyingPeriod, + ])->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $em->persist($entity); + $em->flush(); + + $this->addFlash('success', $this->get('translator')->trans('Success : activity created!')); + + $params = $this->buildParamsToUrl($person, $accompanyingPeriod); + $params['id'] = $entity->getId(); + + return $this->redirectToRoute('chill_activity_activity_show', $params); + } + + if ($view === null) { + throw $this->createNotFoundException('Template not found'); + } + + $activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']); + + return $this->render($view, [ + 'person' => $person, + 'accompanyingCourse' => $accompanyingPeriod, + 'entity' => $entity, + 'form' => $form->createView(), + 'activity_json' => $activity_array + ]); + } + + public function showAction(Request $request, $id): Response + { + $em = $this->getDoctrine()->getManager(); + + [$person, $accompanyingPeriod] = $this->getEntity($request); + + if ($accompanyingPeriod instanceof AccompanyingPeriod) { + $view = 'ChillCalendarBundle:Calendar:showAccompanyingCourse.html.twig'; + } elseif ($person instanceof Person) { + $view = 'ChillCalendarBundle:Calendar:showPerson.html.twig'; + } + + $entity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id); + + if (!$entity) { + throw $this->createNotFoundException('Unable to find Calendar entity.'); + } + + if (null !== $accompanyingPeriod) { + $entity->personsAssociated = $entity->getPersonsAssociated(); + $entity->personsNotAssociated = $entity->getPersonsNotAssociated(); + } + + // TODO revoir le Voter de Activity pour tenir compte qu'une activité peut appartenir a une période + // $this->denyAccessUnlessGranted('CHILL_ACTIVITY_SEE', $entity); + + $deleteForm = $this->createDeleteForm($id, $person, $accompanyingPeriod); + + // TODO + /* + $event = new PrivacyEvent($person, array( + 'element_class' => Activity::class, + 'element_id' => $entity->getId(), + 'action' => 'show' + )); + $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); + */ + + if ($view === null) { + throw $this->createNotFoundException('Template not found'); + } + + return $this->render($view, array( + 'person' => $person, + 'accompanyingCourse' => $accompanyingPeriod, + 'entity' => $entity, + 'delete_form' => $deleteForm->createView(), + )); + } + + /** + * Displays a form to edit an existing Activity entity. + * + */ + public function editAction($id, Request $request): Response + { + $em = $this->getDoctrine()->getManager(); + + [$person, $accompanyingPeriod] = $this->getEntity($request); + + if ($accompanyingPeriod instanceof AccompanyingPeriod) { + $view = 'ChillCalendarBundle:Calendar:editAccompanyingCourse.html.twig'; + } elseif ($person instanceof Person) { + $view = 'ChillCalendarBundle:Calendar:editPerson.html.twig'; + } + + $entity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id); + + if (!$entity) { + throw $this->createNotFoundException('Unable to find Calendar entity.'); + } + + // TODO + // $this->denyAccessUnlessGranted('CHILL_ACTIVITY_UPDATE', $entity); + + $form = $this->createForm(CalendarType::class, $entity, [ + 'center' => $entity->getCenter(), + 'role' => new Role('CHILL_ACTIVITY_UPDATE'), + 'activityType' => $entity->getType(), + 'accompanyingPeriod' => $accompanyingPeriod, + ])->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $em->persist($entity); + $em->flush(); + + $this->addFlash('success', $this->get('translator')->trans('Success : activity updated!')); + + $params = $this->buildParamsToUrl($person, $accompanyingPeriod); + $params['id'] = $id; + return $this->redirectToRoute('chill_activity_activity_show', $params); + } + + $deleteForm = $this->createDeleteForm($id, $person, $accompanyingPeriod); + + /* + * TODO + $event = new PrivacyEvent($person, array( + 'element_class' => Calendar::class, + 'element_id' => $entity->getId(), + 'action' => 'edit' + )); + $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); + */ + + if ($view === null) { + throw $this->createNotFoundException('Template not found'); + } + + $activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']); + + return $this->render($view, array( + 'entity' => $entity, + 'edit_form' => $form->createView(), + 'delete_form' => $deleteForm->createView(), + 'person' => $person, + 'accompanyingCourse' => $accompanyingPeriod, + 'activity_json' => $activity_array + )); + } + + /** + * Deletes a Calendar entity. + * + */ + public function deleteAction(Request $request, $id) + { + $em = $this->getDoctrine()->getManager(); + + [$person, $accompanyingPeriod] = $this->getEntity($request); + + if ($accompanyingPeriod instanceof AccompanyingPeriod) { + $view = 'ChillCalendarBundle:Calendar:confirm_deleteAccompanyingCourse.html.twig'; + } elseif ($person instanceof Person) { + $view = 'ChillCalendarBundle:Calendar:confirm_deletePerson.html.twig'; + } + + /* @var $activity Calendar */ + $activity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id); + + if (!$activity) { + throw $this->createNotFoundException('Unable to find Calendar entity.'); + } + + // TODO + // $this->denyAccessUnlessGranted('CHILL_ACTIVITY_DELETE', $activity); + + $form = $this->createDeleteForm($id, $person, $accompanyingPeriod); + + if ($request->getMethod() === Request::METHOD_DELETE) { + $form->handleRequest($request); + + if ($form->isValid()) { + + $this->logger->notice("An activity has been removed", array( + 'by_user' => $this->getUser()->getUsername(), + 'activity_id' => $activity->getId(), + 'person_id' => $activity->getPerson() ? $activity->getPerson()->getId() : null, + 'comment' => $activity->getComment()->getComment(), + 'scope_id' => $activity->getScope() ? $activity->getScope()->getId() : null, + 'reasons_ids' => $activity->getReasons() + ->map(function ($ar) { return $ar->getId(); }) + ->toArray(), + 'type_id' => $activity->getType()->getId(), + 'duration' => $activity->getDurationTime() ? $activity->getDurationTime()->format('U') : null, + 'date' => $activity->getDate()->format('Y-m-d'), + 'attendee' => $activity->getAttendee() + )); + + $em->remove($activity); + $em->flush(); + + $this->addFlash('success', $this->get('translator') + ->trans("The activity has been successfully removed.")); + + $params = $this->buildParamsToUrl($person, $accompanyingPeriod); + return $this->redirectToRoute('chill_activity_activity_list', $params); + } + } + + if ($view === null) { + throw $this->createNotFoundException('Template not found'); + } + + return $this->render($view, array( + 'activity' => $activity, + 'delete_form' => $form->createView(), + 'person' => $person, + 'accompanyingCourse' => $accompanyingPeriod, + )); + } + + /** + * Creates a form to delete a Calendar entity by id. + */ + private function createDeleteForm(int $id, ?Person $person, ?AccompanyingPeriod $accompanyingPeriod): Form + { + $params = $this->buildParamsToUrl($person, $accompanyingPeriod); + $params['id'] = $id; + + return $this->createFormBuilder() + ->setAction($this->generateUrl('chill_activity_activity_delete', $params)) + ->setMethod('DELETE') + ->add('submit', SubmitType::class, array('label' => 'Delete')) + ->getForm() + ; + } + + private function getEntity(Request $request): array + { + $em = $this->getDoctrine()->getManager(); + $person = $accompanyingPeriod = null; + + if ($request->query->has('person_id')) { + $person_id = $request->get('person_id'); + $person = $em->getRepository(Person::class)->find($person_id); + + if ($person === null) { + throw $this->createNotFoundException('Person not found'); + } + + $this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person); + } elseif ($request->query->has('accompanying_period_id')) { + $accompanying_period_id = $request->get('accompanying_period_id'); + $accompanyingPeriod = $em->getRepository(AccompanyingPeriod::class)->find($accompanying_period_id); + + if ($accompanyingPeriod === null) { + throw $this->createNotFoundException('Accompanying Period not found'); + } + + // TODO Add permission + // $this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person); + } else { + throw $this->createNotFoundException("Person or Accompanying Period not found"); + } + + return [ + $person, $accompanyingPeriod + ]; + } + + private function buildParamsToUrl( + ?Person $person, + ?AccompanyingPeriod $accompanyingPeriod + ): array { + $params = []; + + if ($person) { + $params['person_id'] = $person->getId(); + } + + if ($accompanyingPeriod) { + $params['accompanying_period_id'] = $accompanyingPeriod->getId(); + } + + return $params; + } +} diff --git a/src/Bundle/ChillCalendarBundle/DataFixtures/ORM/LoadCancelReason.php b/src/Bundle/ChillCalendarBundle/DataFixtures/ORM/LoadCancelReason.php new file mode 100644 index 000000000..d9e92a049 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/DataFixtures/ORM/LoadCancelReason.php @@ -0,0 +1,46 @@ + array('fr' => 'Annulé par l\'utilisateur')), + array('name' => array('fr' => 'Annulé par l\'usager')), + array('name' => array('fr' => 'Ne pas comptabiliser')), + ); + + foreach ($arr as $a) { + print "Creating calendar cancel reason : " . $a['name']['fr'] . "\n"; + $cancelReason= (new CancelReason()) + ->setCanceledBy($a['name']) + ->setActive(true); + $manager->persist($cancelReason); + $reference = 'CancelReason_'.$a['name']['fr']; + $this->addReference($reference, $cancelReason); + static::$references[] = $reference; + } + + $manager->flush(); + } +} diff --git a/src/Bundle/ChillCalendarBundle/DataFixtures/ORM/LoadInvite.php b/src/Bundle/ChillCalendarBundle/DataFixtures/ORM/LoadInvite.php new file mode 100644 index 000000000..93d5f6f55 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/DataFixtures/ORM/LoadInvite.php @@ -0,0 +1,44 @@ + array('fr' => 'Rendez-vous décliné')), + array('name' => array('fr' => 'Rendez-vous accepté')), + ); + + foreach ($arr as $a) { + print "Creating calendar invite : " . $a['name']['fr'] . "\n"; + $invite= (new Invite()) + ->setStatus($a['name']); + $manager->persist($invite); + $reference = 'Invite_'.$a['name']['fr']; + $this->addReference($reference, $invite); + static::$references[] = $reference; + } + + $manager->flush(); + } +} diff --git a/src/Bundle/ChillCalendarBundle/DependencyInjection/ChillCalendarExtension.php b/src/Bundle/ChillCalendarBundle/DependencyInjection/ChillCalendarExtension.php new file mode 100644 index 000000000..a1f68da1e --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/DependencyInjection/ChillCalendarExtension.php @@ -0,0 +1,48 @@ +processConfiguration($configuration, $configs); + + $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../config')); + $loader->load('services/fixtures.yaml'); + } + + public function prepend(ContainerBuilder $container) + { + // $this->preprendRoutes($container); + } + + // protected function preprendRoutes(ContainerBuilder $container) + // { + + // $container->prependExtensionConfig('chill_main', array( + // 'routing' => array( + // 'resources' => array( + // '@ChillCalendarBundle/config/routes.yaml' + // ) + // ) + // )); + // } + + +} diff --git a/src/Bundle/ChillCalendarBundle/DependencyInjection/Configuration.php b/src/Bundle/ChillCalendarBundle/DependencyInjection/Configuration.php new file mode 100644 index 000000000..40524b53e --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/DependencyInjection/Configuration.php @@ -0,0 +1,29 @@ +getRootNode('chill_calendar'); + + // Here you should define the parameters that are allowed to + // configure your bundle. See the documentation linked above for + // more information on that topic. + + return $treeBuilder; + } +} diff --git a/src/Bundle/ChillCalendarBundle/Entity/CancelReason.php b/src/Bundle/ChillCalendarBundle/Entity/CancelReason.php index dacb2fd5e..6a21b215c 100644 --- a/src/Bundle/ChillCalendarBundle/Entity/CancelReason.php +++ b/src/Bundle/ChillCalendarBundle/Entity/CancelReason.php @@ -24,7 +24,7 @@ class CancelReason private $active; /** - * @ORM\Column(type="string", length=255) + * @ORM\Column(type="json_array") */ private $canceledBy; @@ -50,12 +50,12 @@ class CancelReason return $this; } - public function getCanceledBy(): ?string + public function getCanceledBy(): ?array { return $this->canceledBy; } - public function setCanceledBy(string $canceledBy): self + public function setCanceledBy(array $canceledBy): self { $this->canceledBy = $canceledBy; diff --git a/src/Bundle/ChillCalendarBundle/Entity/Invite.php b/src/Bundle/ChillCalendarBundle/Entity/Invite.php index c1f792d7d..9b44a93ee 100644 --- a/src/Bundle/ChillCalendarBundle/Entity/Invite.php +++ b/src/Bundle/ChillCalendarBundle/Entity/Invite.php @@ -25,21 +25,21 @@ class Invite private User $user; /** - * @ORM\Column(type="string", length=255) + * @ORM\Column(type="json_array") */ - private $status; + private $status = []; public function getId(): ?int { return $this->id; } - public function getStatus(): ?string + public function getStatus(): ?array { return $this->status; } - public function setStatus(string $status): self + public function setStatus(array $status): self { $this->status = $status; diff --git a/src/Bundle/ChillCalendarBundle/config/services/fixtures.yaml b/src/Bundle/ChillCalendarBundle/config/services/fixtures.yaml new file mode 100644 index 000000000..235856a4b --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/config/services/fixtures.yaml @@ -0,0 +1,8 @@ +--- +services: + Chill\CalendarBundle\DataFixtures\ORM\LoadCancelReason: + tags: + - { 'name': doctrine.fixture.orm } + Chill\CalendarBundle\DataFixtures\ORM\LoadInvite: + tags: + - { 'name': doctrine.fixture.orm } diff --git a/src/Bundle/ChillCalendarBundle/migrations/Version20210715141731.php b/src/Bundle/ChillCalendarBundle/migrations/Version20210715141731.php index e93358fb7..7e535fe27 100644 --- a/src/Bundle/ChillCalendarBundle/migrations/Version20210715141731.php +++ b/src/Bundle/ChillCalendarBundle/migrations/Version20210715141731.php @@ -49,9 +49,11 @@ final class Version20210715141731 extends AbstractMigration $this->addSql('CREATE INDEX IDX_38D57D05A76ED395 ON chill_calendar.calendar_range (user_id)'); $this->addSql('COMMENT ON COLUMN chill_calendar.calendar_range.startDate IS \'(DC2Type:date_immutable)\''); $this->addSql('COMMENT ON COLUMN chill_calendar.calendar_range.endDate IS \'(DC2Type:date_immutable)\''); - $this->addSql('CREATE TABLE chill_calendar.cancel_reason (id INT NOT NULL, active BOOLEAN NOT NULL, canceledBy VARCHAR(255) NOT NULL, name JSON NOT NULL, PRIMARY KEY(id))'); + $this->addSql('CREATE TABLE chill_calendar.cancel_reason (id INT NOT NULL, active BOOLEAN NOT NULL, canceledBy JSON NOT NULL, name JSON NOT NULL, PRIMARY KEY(id))'); $this->addSql('COMMENT ON COLUMN chill_calendar.cancel_reason.name IS \'(DC2Type:json_array)\''); - $this->addSql('CREATE TABLE chill_calendar.invite (id INT NOT NULL, user_id INT DEFAULT NULL, status VARCHAR(255) NOT NULL, PRIMARY KEY(id))'); + $this->addSql('COMMENT ON COLUMN chill_calendar.cancel_reason.canceledBy IS \'(DC2Type:json_array)\''); + $this->addSql('CREATE TABLE chill_calendar.invite (id INT NOT NULL, user_id INT DEFAULT NULL, status JSON NOT NULL, PRIMARY KEY(id))'); + $this->addSql('COMMENT ON COLUMN chill_calendar.invite.status IS \'(DC2Type:json_array)\''); $this->addSql('CREATE INDEX IDX_F517FFA7A76ED395 ON chill_calendar.invite (user_id)'); $this->addSql('ALTER TABLE chill_calendar.calendar ADD CONSTRAINT FK_712315ACA76ED395 FOREIGN KEY (user_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); $this->addSql('ALTER TABLE chill_calendar.calendar ADD CONSTRAINT FK_712315ACD7FA8EF0 FOREIGN KEY (accompanyingPeriod_id) REFERENCES chill_person_accompanying_period (id) NOT DEFERRABLE INITIALLY IMMEDIATE'); @@ -72,7 +74,7 @@ final class Version20210715141731 extends AbstractMigration } public function down(Schema $schema): void - { + { $this->addSql('ALTER TABLE chill_calendar.calendar_to_persons DROP CONSTRAINT FK_AEE94715A40A2C8'); $this->addSql('ALTER TABLE chill_calendar.calendar_to_non_professionals DROP CONSTRAINT FK_FADF2C77A40A2C8'); $this->addSql('ALTER TABLE chill_calendar.calendar_to_thirdparties DROP CONSTRAINT FK_2BAB7EFDA40A2C8'); @@ -92,5 +94,6 @@ final class Version20210715141731 extends AbstractMigration $this->addSql('DROP TABLE chill_calendar.calendar_range'); $this->addSql('DROP TABLE chill_calendar.cancel_reason'); $this->addSql('DROP TABLE chill_calendar.invite'); + $this->addSql('DROP SCHEMA chill_calendar'); } } From b01eba2533887432a40bc6f42f48b479e800c504 Mon Sep 17 00:00:00 2001 From: nobohan Date: Fri, 16 Jul 2021 11:58:30 +0200 Subject: [PATCH 06/59] rdv: add route, twig for listing and creating calendar items --- .../Controller/CalendarController.php | 551 +++++++++--------- .../ChillCalendarExtension.php | 28 +- .../Repository/CalendarRepository.php | 2 +- .../Resources/config/routing.yml | 3 + .../Resources/config/services.yml | 8 + .../Resources/config/services/controller.yml | 5 + .../config/services/fixtures.yml} | 0 .../Resources/views/Calendar/list.html.twig | 189 ++++++ .../listByAccompanyingCourse.html.twig | 9 + .../Resources/views/Calendar/new.html.twig | 0 .../Calendar/newAccompanyingCourse.html.twig | 37 ++ 11 files changed, 540 insertions(+), 292 deletions(-) create mode 100644 src/Bundle/ChillCalendarBundle/Resources/config/routing.yml create mode 100644 src/Bundle/ChillCalendarBundle/Resources/config/services.yml create mode 100644 src/Bundle/ChillCalendarBundle/Resources/config/services/controller.yml rename src/Bundle/ChillCalendarBundle/{config/services/fixtures.yaml => Resources/config/services/fixtures.yml} (100%) create mode 100644 src/Bundle/ChillCalendarBundle/Resources/views/Calendar/list.html.twig create mode 100644 src/Bundle/ChillCalendarBundle/Resources/views/Calendar/listByAccompanyingCourse.html.twig create mode 100644 src/Bundle/ChillCalendarBundle/Resources/views/Calendar/new.html.twig create mode 100644 src/Bundle/ChillCalendarBundle/Resources/views/Calendar/newAccompanyingCourse.html.twig diff --git a/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php b/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php index 616829f19..92771ed32 100644 --- a/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php +++ b/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php @@ -36,7 +36,9 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Core\Role\Role; use Chill\CalendarBundle\Entity\Calendar; use Chill\CalendarBundle\Form\CalendarType; +use Chill\MainBundle\Entity\User; use Symfony\Component\Serializer\SerializerInterface; +use Symfony\Component\Routing\Annotation\Route; /** * Class CalendarController @@ -67,381 +69,374 @@ class CalendarController extends AbstractController /** * Lists all Calendar entities. + * @Route("/{_locale}/calendar/", name="chill_calendar_calendar") */ public function listAction(Request $request): Response { $em = $this->getDoctrine()->getManager(); $view = null; - [$person, $accompanyingPeriod] = $this->getEntity($request); + [$user, $accompanyingPeriod] = $this->getEntity($request); - if ($person instanceof Person) { - $reachableScopes = $this->authorizationHelper - ->getReachableCircles($this->getUser(), new Role('CHILL_Calendar_SEE'), - $person->getCenter()); + if ($user instanceof User) { - $activities = $em->getRepository(Calendar::class) - ->findByPersonImplied($person, $reachableScopes) - ; + // $calendar = $em->getRepository(Calendar::class) + // ->findByUser($user) + // ; - $event = new PrivacyEvent($person, array( - 'element_class' => Calendar::class, - 'action' => 'list' - )); - $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); - - $view = 'ChillCalendarBundle:Calendar:listPerson.html.twig'; + // $view = 'ChillCalendarBundle:Calendar:listByUser.html.twig'; } elseif ($accompanyingPeriod instanceof AccompanyingPeriod) { - $activities = $em->getRepository('ChillCalendarBundle:Calendar')->findBy( - ['accompanyingPeriod' => $accompanyingPeriod], - ['date' => 'DESC'], + $calendarItems = $em->getRepository(Calendar::class)->findBy( + ['accompanyingPeriod' => $accompanyingPeriod] ); - $view = 'ChillCalendarBundle:Calendar:listAccompanyingCourse.html.twig'; + $view = 'ChillCalendarBundle:Calendar:listByAccompanyingCourse.html.twig'; } return $this->render($view, array( - 'activities' => $activities, - 'person' => $person, + 'calendarItems' => $calendarItems, + 'user' => $user, 'accompanyingCourse' => $accompanyingPeriod, )); } - public function selectTypeAction(Request $request): Response - { - $em = $this->getDoctrine()->getManager(); - $view = null; + // public function selectTypeAction(Request $request): Response + // { + // $em = $this->getDoctrine()->getManager(); + // $view = null; - [$person, $accompanyingPeriod] = $this->getEntity($request); + // [$person, $accompanyingPeriod] = $this->getEntity($request); - if ($accompanyingPeriod instanceof AccompanyingPeriod) { - $view = 'ChillCalendarBundle:Calendar:selectTypeAccompanyingCourse.html.twig'; - } elseif ($person instanceof Person) { - $view = 'ChillCalendarBundle:Calendar:selectTypePerson.html.twig'; - } + // if ($accompanyingPeriod instanceof AccompanyingPeriod) { + // $view = 'ChillCalendarBundle:Calendar:selectTypeAccompanyingCourse.html.twig'; + // } elseif ($person instanceof Person) { + // $view = 'ChillCalendarBundle:Calendar:selectTypePerson.html.twig'; + // } - $data = []; + // $data = []; - $activityTypeCategories = $em->getRepository(\Chill\CalendarBundle\Entity\ActivityTypeCategory::class) - ->findBy(['active' => true], ['ordering' => 'ASC']); + // $activityTypeCategories = $em->getRepository(\Chill\CalendarBundle\Entity\ActivityTypeCategory::class) + // ->findBy(['active' => true], ['ordering' => 'ASC']); - foreach ($activityTypeCategories as $activityTypeCategory) { - $activityTypes = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityType::class) - ->findBy(['active' => true, 'category' => $activityTypeCategory], ['ordering' => 'ASC']); + // foreach ($activityTypeCategories as $activityTypeCategory) { + // $activityTypes = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityType::class) + // ->findBy(['active' => true, 'category' => $activityTypeCategory], ['ordering' => 'ASC']); - $data[] = [ - 'activityTypeCategory' => $activityTypeCategory, - 'activityTypes' => $activityTypes, - ]; - } + // $data[] = [ + // 'activityTypeCategory' => $activityTypeCategory, + // 'activityTypes' => $activityTypes, + // ]; + // } - if ($view === null) { - throw $this->createNotFoundException('Template not found'); - } + // if ($view === null) { + // throw $this->createNotFoundException('Template not found'); + // } - return $this->render($view, [ - 'person' => $person, - 'accompanyingCourse' => $accompanyingPeriod, - 'data' => $data, - ]); - } + // return $this->render($view, [ + // 'person' => $person, + // 'accompanyingCourse' => $accompanyingPeriod, + // 'data' => $data, + // ]); + // } + /** + * Create a new calendar item + * @Route("/{_locale}/calendar/new", name="chill_calendar_calendar_new") + */ public function newAction(Request $request): Response { $em = $this->getDoctrine()->getManager(); - [$person, $accompanyingPeriod] = $this->getEntity($request); + [$user, $accompanyingPeriod] = $this->getEntity($request); if ($accompanyingPeriod instanceof AccompanyingPeriod) { $view = 'ChillCalendarBundle:Calendar:newAccompanyingCourse.html.twig'; - } elseif ($person instanceof Person) { - $view = 'ChillCalendarBundle:Calendar:newPerson.html.twig'; - } + } + // elseif ($user instanceof User) { + // $view = 'ChillCalendarBundle:Calendar:newUser.html.twig'; + // } - $activityType_id = $request->get('activityType_id', 0); - $activityType = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityType::class) - ->find($activityType_id); + // $activityType_id = $request->get('activityType_id', 0); + // $activityType = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityType::class) + // ->find($activityType_id); - if (!$activityType instanceof \Chill\ActivityBundle\Entity\ActivityType || - !$activityType->isActive()) { + // if (!$activityType instanceof \Chill\ActivityBundle\Entity\ActivityType || + // !$activityType->isActive()) { - $params = $this->buildParamsToUrl($person, $accompanyingPeriod); - return $this->redirectToRoute('chill_activity_activity_select_type', $params); - } + // $params = $this->buildParamsToUrl($user, $accompanyingPeriod); + // return $this->redirectToRoute('chill_activity_activity_select_type', $params); + // } $entity = new Calendar(); $entity->setUser($this->getUser()); - if ($person instanceof Person) { - $entity->setPerson($person); - } + // if ($user instanceof User) { + // $entity->setPerson($user); + // } if ($accompanyingPeriod instanceof AccompanyingPeriod) { $entity->setAccompanyingPeriod($accompanyingPeriod); } - $entity->setType($activityType); - $entity->setDate(new \DateTime('now')); + // $entity->setType($activityType); + // $entity->setDate(new \DateTime('now')); - // TODO revoir le Voter de Activity pour tenir compte qu'une activité peut appartenir a une période - // $this->denyAccessUnlessGranted('CHILL_ACTIVITY_CREATE', $entity); + // $form = $this->createForm(ActivityType::class, $entity, [ + // 'center' => $entity->getCenter(), + // 'role' => new Role('CHILL_ACTIVITY_CREATE'), + // 'activityType' => $entity->getType(), + // 'accompanyingPeriod' => $accompanyingPeriod, + // ])->handleRequest($request); - $form = $this->createForm(ActivityType::class, $entity, [ - 'center' => $entity->getCenter(), - 'role' => new Role('CHILL_ACTIVITY_CREATE'), - 'activityType' => $entity->getType(), - 'accompanyingPeriod' => $accompanyingPeriod, - ])->handleRequest($request); + // if ($form->isSubmitted() && $form->isValid()) { + // $em->persist($entity); + // $em->flush(); - if ($form->isSubmitted() && $form->isValid()) { - $em->persist($entity); - $em->flush(); + // $this->addFlash('success', $this->get('translator')->trans('Success : activity created!')); - $this->addFlash('success', $this->get('translator')->trans('Success : activity created!')); + // $params = $this->buildParamsToUrl($person, $accompanyingPeriod); + // $params['id'] = $entity->getId(); - $params = $this->buildParamsToUrl($person, $accompanyingPeriod); - $params['id'] = $entity->getId(); + // return $this->redirectToRoute('chill_activity_activity_show', $params); + // } - return $this->redirectToRoute('chill_activity_activity_show', $params); - } + // if ($view === null) { + // throw $this->createNotFoundException('Template not found'); + // } - if ($view === null) { - throw $this->createNotFoundException('Template not found'); - } - - $activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']); + // $activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']); return $this->render($view, [ - 'person' => $person, + 'user' => $user, 'accompanyingCourse' => $accompanyingPeriod, 'entity' => $entity, - 'form' => $form->createView(), - 'activity_json' => $activity_array + // 'form' => $form->createView(), + //'activity_json' => $calendar_array ]); } - public function showAction(Request $request, $id): Response - { - $em = $this->getDoctrine()->getManager(); + // public function showAction(Request $request, $id): Response + // { + // $em = $this->getDoctrine()->getManager(); - [$person, $accompanyingPeriod] = $this->getEntity($request); + // [$person, $accompanyingPeriod] = $this->getEntity($request); - if ($accompanyingPeriod instanceof AccompanyingPeriod) { - $view = 'ChillCalendarBundle:Calendar:showAccompanyingCourse.html.twig'; - } elseif ($person instanceof Person) { - $view = 'ChillCalendarBundle:Calendar:showPerson.html.twig'; - } + // if ($accompanyingPeriod instanceof AccompanyingPeriod) { + // $view = 'ChillCalendarBundle:Calendar:showAccompanyingCourse.html.twig'; + // } elseif ($person instanceof Person) { + // $view = 'ChillCalendarBundle:Calendar:showPerson.html.twig'; + // } - $entity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id); + // $entity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id); - if (!$entity) { - throw $this->createNotFoundException('Unable to find Calendar entity.'); - } + // if (!$entity) { + // throw $this->createNotFoundException('Unable to find Calendar entity.'); + // } - if (null !== $accompanyingPeriod) { - $entity->personsAssociated = $entity->getPersonsAssociated(); - $entity->personsNotAssociated = $entity->getPersonsNotAssociated(); - } + // if (null !== $accompanyingPeriod) { + // $entity->personsAssociated = $entity->getPersonsAssociated(); + // $entity->personsNotAssociated = $entity->getPersonsNotAssociated(); + // } - // TODO revoir le Voter de Activity pour tenir compte qu'une activité peut appartenir a une période - // $this->denyAccessUnlessGranted('CHILL_ACTIVITY_SEE', $entity); + // // TODO revoir le Voter de Activity pour tenir compte qu'une activité peut appartenir a une période + // // $this->denyAccessUnlessGranted('CHILL_ACTIVITY_SEE', $entity); - $deleteForm = $this->createDeleteForm($id, $person, $accompanyingPeriod); + // $deleteForm = $this->createDeleteForm($id, $person, $accompanyingPeriod); - // TODO - /* - $event = new PrivacyEvent($person, array( - 'element_class' => Activity::class, - 'element_id' => $entity->getId(), - 'action' => 'show' - )); - $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); - */ + // // TODO + // /* + // $event = new PrivacyEvent($person, array( + // 'element_class' => Activity::class, + // 'element_id' => $entity->getId(), + // 'action' => 'show' + // )); + // $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); + // */ - if ($view === null) { - throw $this->createNotFoundException('Template not found'); - } + // if ($view === null) { + // throw $this->createNotFoundException('Template not found'); + // } - return $this->render($view, array( - 'person' => $person, - 'accompanyingCourse' => $accompanyingPeriod, - 'entity' => $entity, - 'delete_form' => $deleteForm->createView(), - )); - } + // return $this->render($view, array( + // 'person' => $person, + // 'accompanyingCourse' => $accompanyingPeriod, + // 'entity' => $entity, + // 'delete_form' => $deleteForm->createView(), + // )); + // } - /** - * Displays a form to edit an existing Activity entity. - * - */ - public function editAction($id, Request $request): Response - { - $em = $this->getDoctrine()->getManager(); + // /** + // * Displays a form to edit an existing Activity entity. + // * + // */ + // public function editAction($id, Request $request): Response + // { + // $em = $this->getDoctrine()->getManager(); - [$person, $accompanyingPeriod] = $this->getEntity($request); + // [$person, $accompanyingPeriod] = $this->getEntity($request); - if ($accompanyingPeriod instanceof AccompanyingPeriod) { - $view = 'ChillCalendarBundle:Calendar:editAccompanyingCourse.html.twig'; - } elseif ($person instanceof Person) { - $view = 'ChillCalendarBundle:Calendar:editPerson.html.twig'; - } + // if ($accompanyingPeriod instanceof AccompanyingPeriod) { + // $view = 'ChillCalendarBundle:Calendar:editAccompanyingCourse.html.twig'; + // } elseif ($person instanceof Person) { + // $view = 'ChillCalendarBundle:Calendar:editPerson.html.twig'; + // } - $entity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id); + // $entity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id); - if (!$entity) { - throw $this->createNotFoundException('Unable to find Calendar entity.'); - } + // if (!$entity) { + // throw $this->createNotFoundException('Unable to find Calendar entity.'); + // } - // TODO - // $this->denyAccessUnlessGranted('CHILL_ACTIVITY_UPDATE', $entity); + // // TODO + // // $this->denyAccessUnlessGranted('CHILL_ACTIVITY_UPDATE', $entity); - $form = $this->createForm(CalendarType::class, $entity, [ - 'center' => $entity->getCenter(), - 'role' => new Role('CHILL_ACTIVITY_UPDATE'), - 'activityType' => $entity->getType(), - 'accompanyingPeriod' => $accompanyingPeriod, - ])->handleRequest($request); + // $form = $this->createForm(CalendarType::class, $entity, [ + // 'center' => $entity->getCenter(), + // 'role' => new Role('CHILL_ACTIVITY_UPDATE'), + // 'activityType' => $entity->getType(), + // 'accompanyingPeriod' => $accompanyingPeriod, + // ])->handleRequest($request); - if ($form->isSubmitted() && $form->isValid()) { - $em->persist($entity); - $em->flush(); + // if ($form->isSubmitted() && $form->isValid()) { + // $em->persist($entity); + // $em->flush(); - $this->addFlash('success', $this->get('translator')->trans('Success : activity updated!')); + // $this->addFlash('success', $this->get('translator')->trans('Success : activity updated!')); - $params = $this->buildParamsToUrl($person, $accompanyingPeriod); - $params['id'] = $id; - return $this->redirectToRoute('chill_activity_activity_show', $params); - } + // $params = $this->buildParamsToUrl($person, $accompanyingPeriod); + // $params['id'] = $id; + // return $this->redirectToRoute('chill_activity_activity_show', $params); + // } - $deleteForm = $this->createDeleteForm($id, $person, $accompanyingPeriod); + // $deleteForm = $this->createDeleteForm($id, $person, $accompanyingPeriod); - /* - * TODO - $event = new PrivacyEvent($person, array( - 'element_class' => Calendar::class, - 'element_id' => $entity->getId(), - 'action' => 'edit' - )); - $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); - */ + // /* + // * TODO + // $event = new PrivacyEvent($person, array( + // 'element_class' => Calendar::class, + // 'element_id' => $entity->getId(), + // 'action' => 'edit' + // )); + // $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); + // */ - if ($view === null) { - throw $this->createNotFoundException('Template not found'); - } + // if ($view === null) { + // throw $this->createNotFoundException('Template not found'); + // } - $activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']); + // $activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']); - return $this->render($view, array( - 'entity' => $entity, - 'edit_form' => $form->createView(), - 'delete_form' => $deleteForm->createView(), - 'person' => $person, - 'accompanyingCourse' => $accompanyingPeriod, - 'activity_json' => $activity_array - )); - } + // return $this->render($view, array( + // 'entity' => $entity, + // 'edit_form' => $form->createView(), + // 'delete_form' => $deleteForm->createView(), + // 'person' => $person, + // 'accompanyingCourse' => $accompanyingPeriod, + // 'activity_json' => $activity_array + // )); + // } - /** - * Deletes a Calendar entity. - * - */ - public function deleteAction(Request $request, $id) - { - $em = $this->getDoctrine()->getManager(); + // /** + // * Deletes a Calendar entity. + // * + // */ + // public function deleteAction(Request $request, $id) + // { + // $em = $this->getDoctrine()->getManager(); - [$person, $accompanyingPeriod] = $this->getEntity($request); + // [$person, $accompanyingPeriod] = $this->getEntity($request); - if ($accompanyingPeriod instanceof AccompanyingPeriod) { - $view = 'ChillCalendarBundle:Calendar:confirm_deleteAccompanyingCourse.html.twig'; - } elseif ($person instanceof Person) { - $view = 'ChillCalendarBundle:Calendar:confirm_deletePerson.html.twig'; - } + // if ($accompanyingPeriod instanceof AccompanyingPeriod) { + // $view = 'ChillCalendarBundle:Calendar:confirm_deleteAccompanyingCourse.html.twig'; + // } elseif ($person instanceof Person) { + // $view = 'ChillCalendarBundle:Calendar:confirm_deletePerson.html.twig'; + // } - /* @var $activity Calendar */ - $activity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id); + // /* @var $activity Calendar */ + // $activity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id); - if (!$activity) { - throw $this->createNotFoundException('Unable to find Calendar entity.'); - } + // if (!$activity) { + // throw $this->createNotFoundException('Unable to find Calendar entity.'); + // } - // TODO - // $this->denyAccessUnlessGranted('CHILL_ACTIVITY_DELETE', $activity); + // // TODO + // // $this->denyAccessUnlessGranted('CHILL_ACTIVITY_DELETE', $activity); - $form = $this->createDeleteForm($id, $person, $accompanyingPeriod); + // $form = $this->createDeleteForm($id, $person, $accompanyingPeriod); - if ($request->getMethod() === Request::METHOD_DELETE) { - $form->handleRequest($request); + // if ($request->getMethod() === Request::METHOD_DELETE) { + // $form->handleRequest($request); - if ($form->isValid()) { + // if ($form->isValid()) { - $this->logger->notice("An activity has been removed", array( - 'by_user' => $this->getUser()->getUsername(), - 'activity_id' => $activity->getId(), - 'person_id' => $activity->getPerson() ? $activity->getPerson()->getId() : null, - 'comment' => $activity->getComment()->getComment(), - 'scope_id' => $activity->getScope() ? $activity->getScope()->getId() : null, - 'reasons_ids' => $activity->getReasons() - ->map(function ($ar) { return $ar->getId(); }) - ->toArray(), - 'type_id' => $activity->getType()->getId(), - 'duration' => $activity->getDurationTime() ? $activity->getDurationTime()->format('U') : null, - 'date' => $activity->getDate()->format('Y-m-d'), - 'attendee' => $activity->getAttendee() - )); + // $this->logger->notice("An activity has been removed", array( + // 'by_user' => $this->getUser()->getUsername(), + // 'activity_id' => $activity->getId(), + // 'person_id' => $activity->getPerson() ? $activity->getPerson()->getId() : null, + // 'comment' => $activity->getComment()->getComment(), + // 'scope_id' => $activity->getScope() ? $activity->getScope()->getId() : null, + // 'reasons_ids' => $activity->getReasons() + // ->map(function ($ar) { return $ar->getId(); }) + // ->toArray(), + // 'type_id' => $activity->getType()->getId(), + // 'duration' => $activity->getDurationTime() ? $activity->getDurationTime()->format('U') : null, + // 'date' => $activity->getDate()->format('Y-m-d'), + // 'attendee' => $activity->getAttendee() + // )); - $em->remove($activity); - $em->flush(); + // $em->remove($activity); + // $em->flush(); - $this->addFlash('success', $this->get('translator') - ->trans("The activity has been successfully removed.")); + // $this->addFlash('success', $this->get('translator') + // ->trans("The activity has been successfully removed.")); - $params = $this->buildParamsToUrl($person, $accompanyingPeriod); - return $this->redirectToRoute('chill_activity_activity_list', $params); - } - } + // $params = $this->buildParamsToUrl($person, $accompanyingPeriod); + // return $this->redirectToRoute('chill_activity_activity_list', $params); + // } + // } - if ($view === null) { - throw $this->createNotFoundException('Template not found'); - } + // if ($view === null) { + // throw $this->createNotFoundException('Template not found'); + // } - return $this->render($view, array( - 'activity' => $activity, - 'delete_form' => $form->createView(), - 'person' => $person, - 'accompanyingCourse' => $accompanyingPeriod, - )); - } + // return $this->render($view, array( + // 'activity' => $activity, + // 'delete_form' => $form->createView(), + // 'person' => $person, + // 'accompanyingCourse' => $accompanyingPeriod, + // )); + // } - /** - * Creates a form to delete a Calendar entity by id. - */ - private function createDeleteForm(int $id, ?Person $person, ?AccompanyingPeriod $accompanyingPeriod): Form - { - $params = $this->buildParamsToUrl($person, $accompanyingPeriod); - $params['id'] = $id; + // /** + // * Creates a form to delete a Calendar entity by id. + // */ + // private function createDeleteForm(int $id, ?Person $person, ?AccompanyingPeriod $accompanyingPeriod): Form + // { + // $params = $this->buildParamsToUrl($person, $accompanyingPeriod); + // $params['id'] = $id; - return $this->createFormBuilder() - ->setAction($this->generateUrl('chill_activity_activity_delete', $params)) - ->setMethod('DELETE') - ->add('submit', SubmitType::class, array('label' => 'Delete')) - ->getForm() - ; - } + // return $this->createFormBuilder() + // ->setAction($this->generateUrl('chill_activity_activity_delete', $params)) + // ->setMethod('DELETE') + // ->add('submit', SubmitType::class, array('label' => 'Delete')) + // ->getForm() + // ; + // } private function getEntity(Request $request): array { $em = $this->getDoctrine()->getManager(); - $person = $accompanyingPeriod = null; + $user = $accompanyingPeriod = null; - if ($request->query->has('person_id')) { - $person_id = $request->get('person_id'); - $person = $em->getRepository(Person::class)->find($person_id); + if ($request->query->has('user_id')) { + $user_id = $request->get('user_id'); + $user = $em->getRepository(User::class)->find($user_id); - if ($person === null) { - throw $this->createNotFoundException('Person not found'); + if ($user === null) { + throw $this->createNotFoundException('User not found'); } - $this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $person); + $this->denyAccessUnlessGranted('CHILL_PERSON_SEE', $user); } elseif ($request->query->has('accompanying_period_id')) { $accompanying_period_id = $request->get('accompanying_period_id'); $accompanyingPeriod = $em->getRepository(AccompanyingPeriod::class)->find($accompanying_period_id); @@ -457,24 +452,24 @@ class CalendarController extends AbstractController } return [ - $person, $accompanyingPeriod + $user, $accompanyingPeriod ]; } - private function buildParamsToUrl( - ?Person $person, - ?AccompanyingPeriod $accompanyingPeriod - ): array { - $params = []; + // private function buildParamsToUrl( + // ?Person $person, + // ?AccompanyingPeriod $accompanyingPeriod + // ): array { + // $params = []; - if ($person) { - $params['person_id'] = $person->getId(); - } + // if ($person) { + // $params['person_id'] = $person->getId(); + // } - if ($accompanyingPeriod) { - $params['accompanying_period_id'] = $accompanyingPeriod->getId(); - } + // if ($accompanyingPeriod) { + // $params['accompanying_period_id'] = $accompanyingPeriod->getId(); + // } - return $params; - } + // return $params; + // } } diff --git a/src/Bundle/ChillCalendarBundle/DependencyInjection/ChillCalendarExtension.php b/src/Bundle/ChillCalendarBundle/DependencyInjection/ChillCalendarExtension.php index a1f68da1e..5804b93ff 100644 --- a/src/Bundle/ChillCalendarBundle/DependencyInjection/ChillCalendarExtension.php +++ b/src/Bundle/ChillCalendarBundle/DependencyInjection/ChillCalendarExtension.php @@ -23,26 +23,28 @@ class ChillCalendarExtension extends Extension implements PrependExtensionInterf $configuration = new Configuration(); $config = $this->processConfiguration($configuration, $configs); - $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../config')); - $loader->load('services/fixtures.yaml'); + $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); + $loader->load('services.yml'); + $loader->load('services/controller.yml'); + $loader->load('services/fixtures.yml'); } public function prepend(ContainerBuilder $container) { - // $this->preprendRoutes($container); + $this->preprendRoutes($container); } - // protected function preprendRoutes(ContainerBuilder $container) - // { + protected function preprendRoutes(ContainerBuilder $container) + { - // $container->prependExtensionConfig('chill_main', array( - // 'routing' => array( - // 'resources' => array( - // '@ChillCalendarBundle/config/routes.yaml' - // ) - // ) - // )); - // } + $container->prependExtensionConfig('chill_main', array( + 'routing' => array( + 'resources' => array( + '@ChillCalendarBundle/Resources/config/routing.yml' + ) + ) + )); + } } diff --git a/src/Bundle/ChillCalendarBundle/Repository/CalendarRepository.php b/src/Bundle/ChillCalendarBundle/Repository/CalendarRepository.php index 4f99c6d8e..edb51bb35 100644 --- a/src/Bundle/ChillCalendarBundle/Repository/CalendarRepository.php +++ b/src/Bundle/ChillCalendarBundle/Repository/CalendarRepository.php @@ -2,7 +2,7 @@ namespace Chill\CalendarBundle\Repository; -use CalendarBundle\Entity\Calendar; +use Chill\CalendarBundle\Entity\Calendar; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Persistence\ManagerRegistry; diff --git a/src/Bundle/ChillCalendarBundle/Resources/config/routing.yml b/src/Bundle/ChillCalendarBundle/Resources/config/routing.yml new file mode 100644 index 000000000..70ce2b6d4 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Resources/config/routing.yml @@ -0,0 +1,3 @@ +chill_calendar_controllers: + resource: '../../Controller/' + type: annotation diff --git a/src/Bundle/ChillCalendarBundle/Resources/config/services.yml b/src/Bundle/ChillCalendarBundle/Resources/config/services.yml new file mode 100644 index 000000000..4810e877b --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Resources/config/services.yml @@ -0,0 +1,8 @@ +--- +services: + + Chill\CalendarBundle\Repository\: + autowire: true + resource: '../../Repository/' + tags: + - { name: 'doctrine.repository_service' } diff --git a/src/Bundle/ChillCalendarBundle/Resources/config/services/controller.yml b/src/Bundle/ChillCalendarBundle/Resources/config/services/controller.yml new file mode 100644 index 000000000..a0457c5a8 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Resources/config/services/controller.yml @@ -0,0 +1,5 @@ +services: + Chill\CalendarBundle\Controller\: + autowire: true + resource: '../../../Controller' + tags: ['controller.service_arguments'] diff --git a/src/Bundle/ChillCalendarBundle/config/services/fixtures.yaml b/src/Bundle/ChillCalendarBundle/Resources/config/services/fixtures.yml similarity index 100% rename from src/Bundle/ChillCalendarBundle/config/services/fixtures.yaml rename to src/Bundle/ChillCalendarBundle/Resources/config/services/fixtures.yml diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/list.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/list.html.twig new file mode 100644 index 000000000..94b5f772b --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/list.html.twig @@ -0,0 +1,189 @@ +{% set user_id = null %} +{% if user %} + {% set user_id = user.id %} +{% endif %} + +{% set accompanying_course_id = null %} +{% if accompanyingCourse %} + {% set accompanying_course_id = accompanyingCourse.id %} +{% endif %} + +

{{ 'Calendar list' |trans }}

+ +{% if calendarItems|length == 0 %} +

+ {{ "There is no calendar items."|trans }} + +

+{% else %} + +
+ + {% for calendar in calendarItems %} + + + {% set t = calendar.type %} +
+
+
+ + {% if calendar.date %} +

{{ calendar.date|format_date('long') }}

+ {% endif %} + +
+ {% if t.durationTimeVisible > 0 %} +

+ + {{ calendar.durationTime|date('H:i') }} +

+ {% endif %} + + {% if calendar.travelTime and t.travelTimeVisible %} +

+ + {{ calendar.travelTime|date('H:i') }} +

+ {% endif %} +
+ + {% if context == 'user' and calendar.accompanyingPeriod is not empty %} + + {% endif %} + +
+
+
    + {% if calendar.user and t.userVisible %} +
  • + {{ 'by'|trans }}{{ calendar.user.usernameCanonical }} +
  • + {% endif %} + +
  • + {{ calendar.type.name | localize_translatable_string }} + + {% if calendar.attendee is not null and t.attendeeVisible %} + {% if calendar.attendee %} + {{ '→ ' ~ 'present'|trans|capitalize }} + {% else %} + {{ '→ ' ~ 'not present'|trans|capitalize }} + {% endif %} + {% endif %} +
  • + +
  • + {{ 'location'|trans ~ ': ' }} + Domicile de l'usager + {# + {% if calendar.location %}{{ calendar.location }}{% endif %} + #} +
  • + + {%- if t.reasonsVisible -%} +
  • + {%- if calendar.reasons is empty -%} + {{ 'No reason associated'|trans }} + {%- else -%} + {% for r in calendar.reasons %} + {{ r|chill_entity_render_box }} + {% endfor %} + {%- endif -%} +
  • + {% endif %} + + {%- if t.socialIssuesVisible %} + + {% endif %} + + {%- if t.socialActionsVisible -%} + + {% endif %} + + +
+
    +
  • + +
  • + {# TOOD + {% if is_granted('CHILL_ACTIVITY_UPDATE', calendar) %} + #} +
  • + +
  • + {# TOOD + {% endif %} + {% if is_granted('CHILL_ACTIVITY_DELETE', calendar) %} + #} +
  • + +
  • + {# + {% endif %} + #} +
+
+
+ + {% + if calendar.comment.comment is not empty + or calendar.users|length > 0 + or calendar.thirdParties|length > 0 + or calendar.users|length > 0 + %} +
+
+ + {% include 'ChillCalendarBundle:Calendar:concernedGroups.html.twig' with {'context': context, 'with_display': 'row', 'entity': calendar } %} +
+ + {% if calendar.comment.comment is not empty %} +
+ {{ calendar.comment|chill_entity_render_box( { 'limit_lines': 3, 'metadata': false } ) }} +
+ {% endif %} +
+ {% endif %} + +
+ {% endfor %} +
+{% endif %} + +{% if context != 'user' %} +{# TODO set this condition in configuration #} + +{% endif %} diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/listByAccompanyingCourse.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/listByAccompanyingCourse.html.twig new file mode 100644 index 000000000..c0230344d --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/listByAccompanyingCourse.html.twig @@ -0,0 +1,9 @@ +{% extends "@ChillPerson/AccompanyingCourse/layout.html.twig" %} + +{% set activeRouteKey = 'chill_calendar_calendar_list' %} + +{% block title %}{{ 'Calendar list' |trans }}{% endblock title %} + +{% block content %} + {% include 'ChillCalendarBundle:Calendar:list.html.twig' with {'context': 'accompanyingCourse'} %} +{% endblock %} diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/new.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/new.html.twig new file mode 100644 index 000000000..e69de29bb diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/newAccompanyingCourse.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/newAccompanyingCourse.html.twig new file mode 100644 index 000000000..3cc1f9486 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/newAccompanyingCourse.html.twig @@ -0,0 +1,37 @@ +{% extends "@ChillPerson/AccompanyingCourse/layout.html.twig" %} + +{% set activeRouteKey = 'chill_calendar_calendar_new' %} + +{% block title 'Calendar creation' |trans %} + +{% block content %} +
+
+
+ +
{# <=== vue component #} + {% include 'ChillCalendarBundle:Calendar:new.html.twig' with {'context': 'accompanyingCourse'} %} + +
+
+
+{% endblock %} + +{% block js %} + {{ parent() }} + {{ encore_entry_script_tags('async_upload') }} + + {{ encore_entry_script_tags('vue_calendar') }} +{% endblock %} + +{% block css %} + {{ parent() }} + + {{ encore_entry_link_tags('vue_calendar') }} +{% endblock %} From 114df16e0ff40599e0cf34df8a60838829afe926 Mon Sep 17 00:00:00 2001 From: nobohan Date: Fri, 16 Jul 2021 12:57:11 +0200 Subject: [PATCH 07/59] rdv: add new rdv form --- .../Controller/CalendarController.php | 70 +++++++--------- .../ChillCalendarExtension.php | 1 + .../ChillCalendarBundle/Form/CalendarType.php | 80 +++++++++++++++++++ .../Repository/CancelReasonRepository.php | 2 +- .../Repository/InviteRepository.php | 2 +- .../Resources/config/services/form.yml | 9 +++ .../Resources/views/Calendar/new.html.twig | 80 +++++++++++++++++++ .../Calendar/newAccompanyingCourse.html.twig | 3 - 8 files changed, 200 insertions(+), 47 deletions(-) create mode 100644 src/Bundle/ChillCalendarBundle/Form/CalendarType.php create mode 100644 src/Bundle/ChillCalendarBundle/Resources/config/services/form.yml diff --git a/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php b/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php index 92771ed32..4bde0e6f9 100644 --- a/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php +++ b/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php @@ -156,17 +156,6 @@ class CalendarController extends AbstractController // $view = 'ChillCalendarBundle:Calendar:newUser.html.twig'; // } - // $activityType_id = $request->get('activityType_id', 0); - // $activityType = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityType::class) - // ->find($activityType_id); - - // if (!$activityType instanceof \Chill\ActivityBundle\Entity\ActivityType || - // !$activityType->isActive()) { - - // $params = $this->buildParamsToUrl($user, $accompanyingPeriod); - // return $this->redirectToRoute('chill_activity_activity_select_type', $params); - // } - $entity = new Calendar(); $entity->setUser($this->getUser()); @@ -181,28 +170,25 @@ class CalendarController extends AbstractController // $entity->setType($activityType); // $entity->setDate(new \DateTime('now')); - // $form = $this->createForm(ActivityType::class, $entity, [ - // 'center' => $entity->getCenter(), - // 'role' => new Role('CHILL_ACTIVITY_CREATE'), - // 'activityType' => $entity->getType(), - // 'accompanyingPeriod' => $accompanyingPeriod, - // ])->handleRequest($request); + $form = $this->createForm(CalendarType::class, $entity, [ + 'accompanyingPeriod' => $accompanyingPeriod, + ])->handleRequest($request); - // if ($form->isSubmitted() && $form->isValid()) { - // $em->persist($entity); - // $em->flush(); + if ($form->isSubmitted() && $form->isValid()) { + $em->persist($entity); + $em->flush(); - // $this->addFlash('success', $this->get('translator')->trans('Success : activity created!')); + $this->addFlash('success', $this->get('translator')->trans('Success : calendar item created!')); - // $params = $this->buildParamsToUrl($person, $accompanyingPeriod); - // $params['id'] = $entity->getId(); + $params = $this->buildParamsToUrl($user, $accompanyingPeriod); //TODO useful? + $params['id'] = $entity->getId(); - // return $this->redirectToRoute('chill_activity_activity_show', $params); - // } + return $this->redirectToRoute('chill_calendar_calendar_show', $params); + } - // if ($view === null) { - // throw $this->createNotFoundException('Template not found'); - // } + if ($view === null) { + throw $this->createNotFoundException('Template not found'); + } // $activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']); @@ -210,7 +196,7 @@ class CalendarController extends AbstractController 'user' => $user, 'accompanyingCourse' => $accompanyingPeriod, 'entity' => $entity, - // 'form' => $form->createView(), + 'form' => $form->createView(), //'activity_json' => $calendar_array ]); } @@ -456,20 +442,20 @@ class CalendarController extends AbstractController ]; } - // private function buildParamsToUrl( - // ?Person $person, - // ?AccompanyingPeriod $accompanyingPeriod - // ): array { - // $params = []; + private function buildParamsToUrl( + ?User $user, + ?AccompanyingPeriod $accompanyingPeriod + ): array { + $params = []; - // if ($person) { - // $params['person_id'] = $person->getId(); - // } + if ($user) { + $params['user_id'] = $user->getId(); + } - // if ($accompanyingPeriod) { - // $params['accompanying_period_id'] = $accompanyingPeriod->getId(); - // } + if ($accompanyingPeriod) { + $params['accompanying_period_id'] = $accompanyingPeriod->getId(); + } - // return $params; - // } + return $params; + } } diff --git a/src/Bundle/ChillCalendarBundle/DependencyInjection/ChillCalendarExtension.php b/src/Bundle/ChillCalendarBundle/DependencyInjection/ChillCalendarExtension.php index 5804b93ff..f67dfb67f 100644 --- a/src/Bundle/ChillCalendarBundle/DependencyInjection/ChillCalendarExtension.php +++ b/src/Bundle/ChillCalendarBundle/DependencyInjection/ChillCalendarExtension.php @@ -27,6 +27,7 @@ class ChillCalendarExtension extends Extension implements PrependExtensionInterf $loader->load('services.yml'); $loader->load('services/controller.yml'); $loader->load('services/fixtures.yml'); + $loader->load('services/form.yml'); } public function prepend(ContainerBuilder $container) diff --git a/src/Bundle/ChillCalendarBundle/Form/CalendarType.php b/src/Bundle/ChillCalendarBundle/Form/CalendarType.php new file mode 100644 index 000000000..c83fd9859 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Form/CalendarType.php @@ -0,0 +1,80 @@ +translatableStringHelper = $translatableStringHelper; + } + + /** + * {@inheritdoc} + */ + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder + ->add('comment', CommentType::class, array( + 'required' => false + )) + ->add('startDate', DateType::class, array( + 'required' => false, + 'input' => 'datetime_immutable', + 'widget' => 'single_text' + )) + ->add('endDate', DateType::class, array( + 'required' => false, + 'input' => 'datetime_immutable', + 'widget' => 'single_text' + )) + ->add('cancelReason', EntityType::class, array( + 'required' => false, + 'class' => CancelReason::class, + 'choice_label' => function (CancelReason $entity) { + return $this->translatableStringHelper->localize($entity->getName()); + }, + )) + ; + + }/** + * {@inheritdoc} + */ + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults(array( + 'data_class' => Calendar::class + )); + + $resolver + ->setRequired(['accompanyingPeriod']) + ->setAllowedTypes('accompanyingPeriod', [\Chill\PersonBundle\Entity\AccompanyingPeriod::class, 'null']) + ; + } + + /** + * {@inheritdoc} + */ + public function getBlockPrefix() + { + return 'chill_calendarbundle_calendar'; + } + + +} + + diff --git a/src/Bundle/ChillCalendarBundle/Repository/CancelReasonRepository.php b/src/Bundle/ChillCalendarBundle/Repository/CancelReasonRepository.php index 11c2f7f59..5bd07fbd9 100644 --- a/src/Bundle/ChillCalendarBundle/Repository/CancelReasonRepository.php +++ b/src/Bundle/ChillCalendarBundle/Repository/CancelReasonRepository.php @@ -2,7 +2,7 @@ namespace Chill\CalendarBundle\Repository; -use CalendarBundle\Entity\CancelReason; +use Chill\CalendarBundle\Entity\CancelReason; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Persistence\ManagerRegistry; diff --git a/src/Bundle/ChillCalendarBundle/Repository/InviteRepository.php b/src/Bundle/ChillCalendarBundle/Repository/InviteRepository.php index da9207cc4..ece11269f 100644 --- a/src/Bundle/ChillCalendarBundle/Repository/InviteRepository.php +++ b/src/Bundle/ChillCalendarBundle/Repository/InviteRepository.php @@ -2,7 +2,7 @@ namespace Chill\CalendarBundle\Repository; -use CalendarBundle\Entity\Invite; +use Chill\CalendarBundle\Entity\Invite; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Persistence\ManagerRegistry; diff --git a/src/Bundle/ChillCalendarBundle/Resources/config/services/form.yml b/src/Bundle/ChillCalendarBundle/Resources/config/services/form.yml new file mode 100644 index 000000000..12241277f --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Resources/config/services/form.yml @@ -0,0 +1,9 @@ +--- +services: + chill.calendar.form.type.calendar: + class: Chill\CalendarBundle\Form\CalendarType + arguments: + - "@chill.main.helper.translatable_string" + + tags: + - { name: form.type, alias: chill_calendarbundle_calendar } \ No newline at end of file diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/new.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/new.html.twig index e69de29bb..ebb9ac911 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/new.html.twig +++ b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/new.html.twig @@ -0,0 +1,80 @@ +

{{ "Calendar item creation"|trans ~ ' :' }}

+ +{{ form_start(form) }} +{{ form_errors(form) }} + +{%- if form.mainUser is defined -%} + {{ form_widget(form.mainUser) }} +{% endif %} + +

{{ 'Concerned groups'|trans }}

+ +{%- if form.persons is defined -%} + {{ form_widget(form.persons) }} +{% endif %} +{%- if form.nonProfessionals is defined -%} + {{ form_widget(form.nonProfessionals) }} +{% endif %} +{%- if form.users is defined -%} + {{ form_widget(form.users) }} +{% endif %} + +
+ +

{{ 'Calendar data'|trans }}

+ +{%- if form.startDate is defined -%} + {{ form_row(form.startDate) }} +{% endif %} + +{%- if form.endDate is defined -%} + {{ form_row(form.endDate) }} +{% endif %} + +.. location + +{%- if form.status is defined -%} + {{ form_row(form.status) }} +{% endif %} + +{%- if form.cancelReason is defined -%} + {{ form_row(form.cancelReason) }} +{% endif %} + +{%- if form.comment is defined -%} + {{ form_row(form.comment) }} +{% endif %} + +{%- if form.activity is defined -%} + {{ form_row(form.activity) }} +{% endif %} + +{%- if form.sendSMS is defined -%} + {{ form_row(form.sendSMS) }} +{% endif %} + + +..calendarRange + + + + +{{ form_end(form) }} diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/newAccompanyingCourse.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/newAccompanyingCourse.html.twig index 3cc1f9486..72345b98f 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/newAccompanyingCourse.html.twig +++ b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/newAccompanyingCourse.html.twig @@ -25,13 +25,10 @@ chill.displayAlertWhenLeavingUnsubmittedForm('form[name="{{ form.vars.form.vars.name }}"]', '{{ "You are going to leave a page with unsubmitted data. Are you sure you want to leave ?"|trans }}'); }); - window.calendar = {{ calendar_json|json_encode|raw }}; - {{ encore_entry_script_tags('vue_calendar') }} {% endblock %} {% block css %} {{ parent() }} - {{ encore_entry_link_tags('vue_calendar') }} {% endblock %} From 20d113b1db56930a35a1646532aa7dd83a7ba42f Mon Sep 17 00:00:00 2001 From: nobohan Date: Fri, 16 Jul 2021 17:00:21 +0200 Subject: [PATCH 08/59] rdv: some fixes for the new rdv --- src/Bundle/ChillCalendarBundle/Form/CalendarType.php | 11 ++++++++++- .../Repository/CalendarRangeRepository.php | 2 +- .../Resources/views/Calendar/new.html.twig | 4 ---- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/Bundle/ChillCalendarBundle/Form/CalendarType.php b/src/Bundle/ChillCalendarBundle/Form/CalendarType.php index c83fd9859..44a627ed2 100644 --- a/src/Bundle/ChillCalendarBundle/Form/CalendarType.php +++ b/src/Bundle/ChillCalendarBundle/Form/CalendarType.php @@ -7,6 +7,7 @@ use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Form\Extension\Core\Type\DateType; use Symfony\Bridge\Doctrine\Form\Type\EntityType; +use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Chill\MainBundle\Form\Type\CommentType; use Chill\CalendarBundle\Entity\Calendar; @@ -46,9 +47,17 @@ class CalendarType extends AbstractType 'required' => false, 'class' => CancelReason::class, 'choice_label' => function (CancelReason $entity) { - return $this->translatableStringHelper->localize($entity->getName()); + return $this->translatableStringHelper->localize($entity->getCanceledBy()); }, )) + ->add('sendSMS', ChoiceType::class, array( + 'required' => false, + 'choices' => array( + 'Oui' => true, + 'Non' => false + ), + 'expanded' => true + )) ; }/** diff --git a/src/Bundle/ChillCalendarBundle/Repository/CalendarRangeRepository.php b/src/Bundle/ChillCalendarBundle/Repository/CalendarRangeRepository.php index a2c542436..152c0f097 100644 --- a/src/Bundle/ChillCalendarBundle/Repository/CalendarRangeRepository.php +++ b/src/Bundle/ChillCalendarBundle/Repository/CalendarRangeRepository.php @@ -2,7 +2,7 @@ namespace Chill\CalendarBundle\Repository; -use CalendarBundle\Entity\CalendarRange; +use Chill\CalendarBundle\Entity\CalendarRange; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Persistence\ManagerRegistry; diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/new.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/new.html.twig index ebb9ac911..84811aaf4 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/new.html.twig +++ b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/new.html.twig @@ -45,10 +45,6 @@ {{ form_row(form.comment) }} {% endif %} -{%- if form.activity is defined -%} - {{ form_row(form.activity) }} -{% endif %} - {%- if form.sendSMS is defined -%} {{ form_row(form.sendSMS) }} {% endif %} From 1557b8f80abd26e2bcf00b497d4e79ea6108cd25 Mon Sep 17 00:00:00 2001 From: nobohan Date: Fri, 16 Jul 2021 18:21:27 +0200 Subject: [PATCH 09/59] rdv: add the concernedGroup vuejs component in add a new rdv --- .../ChillCalendarBundle/Form/CalendarType.php | 23 +++ .../Resources/public/vuejs/Calendar/App.vue | 14 ++ .../Resources/public/vuejs/Calendar/i18n.js | 27 +++ .../Resources/public/vuejs/Calendar/index.js | 16 ++ .../Resources/public/vuejs/Calendar/store.js | 179 ++++++++++++++++++ .../Calendar/newAccompanyingCourse.html.twig | 3 + .../chill.webpack.config.js | 10 + 7 files changed, 272 insertions(+) create mode 100644 src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue create mode 100644 src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/i18n.js create mode 100644 src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/index.js create mode 100644 src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js create mode 100644 src/Bundle/ChillCalendarBundle/chill.webpack.config.js diff --git a/src/Bundle/ChillCalendarBundle/Form/CalendarType.php b/src/Bundle/ChillCalendarBundle/Form/CalendarType.php index 44a627ed2..36388fa83 100644 --- a/src/Bundle/ChillCalendarBundle/Form/CalendarType.php +++ b/src/Bundle/ChillCalendarBundle/Form/CalendarType.php @@ -13,6 +13,9 @@ use Chill\MainBundle\Form\Type\CommentType; use Chill\CalendarBundle\Entity\Calendar; use Chill\CalendarBundle\Entity\CancelReason; use Chill\MainBundle\Templating\TranslatableStringHelper; +use Chill\PersonBundle\Entity\Person; +use Symfony\Component\Form\CallbackTransformer; +use Symfony\Component\Form\Extension\Core\Type\HiddenType; class CalendarType extends AbstractType { @@ -60,6 +63,26 @@ class CalendarType extends AbstractType )) ; + $builder->add('persons', HiddenType::class); + $builder->get('persons') + ->addModelTransformer(new CallbackTransformer( + function (iterable $personsAsIterable): string { + $personIds = []; + foreach ($personsAsIterable as $value) { + $personIds[] = $value->getId(); + } + return implode(',', $personIds); + }, + function (?string $personsAsString): array { + return array_map( + fn(string $id): ?Person => $this->om->getRepository(Person::class)->findOneBy(['id' => (int) $id]), + explode(',', $personsAsString) + ); + } + )) + ; + + }/** * {@inheritdoc} */ diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue new file mode 100644 index 000000000..f1e8069a7 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue @@ -0,0 +1,14 @@ + + + diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/i18n.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/i18n.js new file mode 100644 index 000000000..3262a37a5 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/i18n.js @@ -0,0 +1,27 @@ +import { personMessages } from 'ChillPersonAssets/vuejs/_js/i18n' + +const appMessages = { + fr: { + activity: { + // + social_issues: "Problématiques sociales", + choose_other_social_issue: "Ajouter une autre problématique sociale...", + social_actions: "Actions d'accompagnement", + select_first_a_social_issue: "Sélectionnez d'abord une problématique sociale", + + // + add_persons: "Ajouter des personnes concernées", + bloc_persons: "Usagers", + bloc_persons_associated: "Usagers du parcours", + bloc_persons_not_associated: "Tiers non-pro.", + bloc_thirdparty: "Tiers professionnels", + bloc_users: "T(M)S", + } + } +} + +Object.assign(appMessages.fr, personMessages.fr); + +export { + appMessages +}; diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/index.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/index.js new file mode 100644 index 000000000..d4c07f4a7 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/index.js @@ -0,0 +1,16 @@ +import { createApp } from 'vue'; +import { _createI18n } from 'ChillMainAssets/vuejs/_js/i18n' +import { appMessages } from './i18n' +import store from './store' + +import App from './App.vue'; + +const i18n = _createI18n(appMessages); + +const app = createApp({ + template: ``, +}) +.use(store) +.use(i18n) +.component('app', App) +.mount('#calendar'); diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js new file mode 100644 index 000000000..91b67aae3 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js @@ -0,0 +1,179 @@ +import 'es6-promise/auto'; +import { createStore } from 'vuex'; + +const debug = process.env.NODE_ENV !== 'production'; +//console.log('window.activity', window.activity); + +const addIdToValue = (string, id) => { + let array = string ? string.split(',') : []; + array.push(id.toString()); + let str = array.join(); + return str; +}; + +const removeIdFromValue = (string, id) => { + let array = string.split(','); + array = array.filter(el => el !== id.toString()); + let str = array.join(); + return str; +}; + + +const activity = { + accompanyingPeriod: null, + socialIssues: [], + persons: [] +}; // TODO: get this object from window.activity ? + +const store = createStore({ + strict: debug, + state: { + activity: activity, + socialIssuesOther: [], + socialActionsList: [], + }, + mutations: { + + // SocialIssueAcc + addIssueInList(state, issue) { + //console.log('add issue list', issue.id); + state.activity.accompanyingPeriod.socialIssues.push(issue); + }, + addIssueSelected(state, issue) { + //console.log('add issue selected', issue.id); + state.activity.socialIssues.push(issue); + }, + updateIssuesSelected(state, issues) { + //console.log('update issues selected', issues); + state.activity.socialIssues = issues; + }, + updateIssuesOther(state, payload) { + //console.log('update issues other'); + state.socialIssuesOther = payload; + }, + removeIssueInOther(state, issue) { + //console.log('remove issue other', issue.id); + state.socialIssuesOther = state.socialIssuesOther.filter(i => i.id !== issue.id); + }, + resetActionsList(state) { + //console.log('reset list actions'); + state.socialActionsList = []; + }, + addActionInList(state, action) { + //console.log('add action list', action.id); + state.socialActionsList.push(action); + }, + updateActionsSelected(state, actions) { + //console.log('update actions selected', actions); + state.activity.socialActions = actions; + }, + filterList(state, list) { + const filterList = (list) => { + // remove duplicates entries + list = list.filter((value, index) => list.findIndex(array => array.id === value.id) === index); + // alpha sort + list.sort((a,b) => (a.text > b.text) ? 1 : ((b.text > a.text) ? -1 : 0)); + return list; + }; + if (list === 'issues') { + state.activity.accompanyingPeriod.socialIssues = filterList(state.activity.accompanyingPeriod.socialIssues); + } + if (list === 'actions') { + state.socialActionsList = filterList(state.socialActionsList); + } + }, + + // ConcernedGroups + addPersonsInvolved(state, payload) { + //console.log('### mutation addPersonsInvolved', payload.result.type); + console.log(state) + console.log(payload) + switch (payload.result.type) { + case 'person': + state.activity.persons.push(payload.result); + break; + case 'thirdparty': + state.activity.thirdParties.push(payload.result); + break; + case 'user': + state.activity.users.push(payload.result); + break; + }; + }, + removePersonInvolved(state, payload) { + //console.log('### mutation removePersonInvolved', payload.type); + switch (payload.type) { + case 'person': + state.activity.persons = state.activity.persons.filter(person => person !== payload); + break; + case 'thirdparty': + state.activity.thirdParties = state.activity.thirdParties.filter(thirdparty => thirdparty !== payload); + break; + case 'user': + state.activity.users = state.activity.users.filter(user => user !== payload); + break; + }; + } + }, + actions: { + addIssueSelected({ commit }, issue) { + let aSocialIssues = document.getElementById("chill_calendarbundle_calendar_socialIssues"); + aSocialIssues.value = addIdToValue(aSocialIssues.value, issue.id); + commit('addIssueSelected', issue); + }, + updateIssuesSelected({ commit }, payload) { + let aSocialIssues = document.getElementById("chill_calendarbundle_calendar_socialIssues"); + aSocialIssues.value = ''; + payload.forEach(item => { + aSocialIssues.value = addIdToValue(aSocialIssues.value, item.id); + }); + commit('updateIssuesSelected', payload); + }, + updateActionsSelected({ commit }, payload) { + let aSocialActions = document.getElementById("chill_calendarbundle_calendar_socialActions"); + aSocialActions.value = ''; + payload.forEach(item => { + aSocialActions.value = addIdToValue(aSocialActions.value, item.id); + }); + commit('updateActionsSelected', payload); + }, + addPersonsInvolved({ commit }, payload) { + //console.log('### action addPersonsInvolved', payload.result.type); + switch (payload.result.type) { + case 'person': + let aPersons = document.getElementById("chill_calendarbundle_calendar_persons"); + aPersons.value = addIdToValue(aPersons.value, payload.result.id); + break; + case 'thirdparty': + let aThirdParties = document.getElementById("chill_calendarbundle_calendar_thirdParties"); + aThirdParties.value = addIdToValue(aThirdParties.value, payload.result.id); + break; + case 'user': + let aUsers = document.getElementById("chill_calendarbundle_calendar_users"); + aUsers.value = addIdToValue(aUsers.value, payload.result.id); + break; + }; + commit('addPersonsInvolved', payload); + }, + removePersonInvolved({ commit }, payload) { + //console.log('### action removePersonInvolved', payload); + switch (payload.type) { + case 'person': + let aPersons = document.getElementById("chill_calendarbundle_calendar_persons"); + aPersons.value = removeIdFromValue(aPersons.value, payload.id); + break; + case 'thirdparty': + let aThirdParties = document.getElementById("chill_calendarbundle_calendar_thirdParties"); + aThirdParties.value = removeIdFromValue(aThirdParties.value, payload.id); + break; + case 'user': + let aUsers = document.getElementById("chill_calendarbundle_calendar_users"); + aUsers.value = removeIdFromValue(aUsers.value, payload.id); + break; + }; + commit('removePersonInvolved', payload); + } + } +}); + +export default store; diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/newAccompanyingCourse.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/newAccompanyingCourse.html.twig index 72345b98f..7d1d27d4c 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/newAccompanyingCourse.html.twig +++ b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/newAccompanyingCourse.html.twig @@ -26,9 +26,12 @@ '{{ "You are going to leave a page with unsubmitted data. Are you sure you want to leave ?"|trans }}'); }); + {{ encore_entry_script_tags('vue_calendar') }} {% endblock %} {% block css %} {{ parent() }} {% endblock %} + + diff --git a/src/Bundle/ChillCalendarBundle/chill.webpack.config.js b/src/Bundle/ChillCalendarBundle/chill.webpack.config.js new file mode 100644 index 000000000..74f1dd6ea --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/chill.webpack.config.js @@ -0,0 +1,10 @@ +// this file loads all assets from the Chill calendar bundle +module.exports = function(encore, entries) { + //entries.push(__dirname + '/Resources/public/index.js'); + + encore.addAliases({ + ChillCalendarAssets: __dirname + '/Resources/public' + }); + + encore.addEntry('vue_calendar', __dirname + '/Resources/public/vuejs/Calendar/index.js'); +}; From 43d6dc835f1d82589763c5538ea649b8dd59be33 Mon Sep 17 00:00:00 2001 From: nobohan Date: Mon, 19 Jul 2021 10:08:43 +0200 Subject: [PATCH 10/59] rdv: add thirdParty in concerned persons (WIP) --- .../ChillCalendarBundle/Form/CalendarType.php | 41 ++++++++++++++++++- .../Resources/public/vuejs/Calendar/i18n.js | 7 ---- .../Resources/public/vuejs/Calendar/store.js | 20 ++++----- .../Resources/views/Calendar/new.html.twig | 3 ++ 4 files changed, 53 insertions(+), 18 deletions(-) diff --git a/src/Bundle/ChillCalendarBundle/Form/CalendarType.php b/src/Bundle/ChillCalendarBundle/Form/CalendarType.php index 36388fa83..7500594ea 100644 --- a/src/Bundle/ChillCalendarBundle/Form/CalendarType.php +++ b/src/Bundle/ChillCalendarBundle/Form/CalendarType.php @@ -14,6 +14,7 @@ use Chill\CalendarBundle\Entity\Calendar; use Chill\CalendarBundle\Entity\CancelReason; use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\PersonBundle\Entity\Person; +use Chill\ThirdPartyBundle\Entity\ThirdParty; use Symfony\Component\Form\CallbackTransformer; use Symfony\Component\Form\Extension\Core\Type\HiddenType; @@ -81,7 +82,45 @@ class CalendarType extends AbstractType } )) ; - + + $builder->add('professionals', HiddenType::class); + $builder->get('professionals') + ->addModelTransformer(new CallbackTransformer( + function (iterable $thirdpartyAsIterable): string { + $thirdpartyIds = []; + foreach ($thirdpartyAsIterable as $value) { + $thirdpartyIds[] = $value->getId(); + } + return implode(',', $thirdpartyIds); + }, + function (?string $thirdpartyAsString): array { + return array_map( + fn(string $id): ?ThirdParty => $this->om->getRepository(ThirdParty::class)->findOneBy(['id' => (int) $id]), + explode(',', $thirdpartyAsString) + ); + } + )) + ; + + // $builder->add('users', HiddenType::class); + // $builder->get('users') + // ->addModelTransformer(new CallbackTransformer( + // function (iterable $usersAsIterable): string { + // $userIds = []; + // foreach ($usersAsIterable as $value) { + // $userIds[] = $value->getId(); + // } + // return implode(',', $userIds); + // }, + // function (?string $usersAsString): array { + // return array_map( + // fn(string $id): ?User => $this->om->getRepository(User::class)->findOneBy(['id' => (int) $id]), + // explode(',', $usersAsString) + // ); + // } + // )) + // ; + }/** * {@inheritdoc} diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/i18n.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/i18n.js index 3262a37a5..778072e61 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/i18n.js +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/i18n.js @@ -3,13 +3,6 @@ import { personMessages } from 'ChillPersonAssets/vuejs/_js/i18n' const appMessages = { fr: { activity: { - // - social_issues: "Problématiques sociales", - choose_other_social_issue: "Ajouter une autre problématique sociale...", - social_actions: "Actions d'accompagnement", - select_first_a_social_issue: "Sélectionnez d'abord une problématique sociale", - - // add_persons: "Ajouter des personnes concernées", bloc_persons: "Usagers", bloc_persons_associated: "Usagers du parcours", diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js index 91b67aae3..2a7ce62f4 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js @@ -22,7 +22,9 @@ const removeIdFromValue = (string, id) => { const activity = { accompanyingPeriod: null, socialIssues: [], - persons: [] + persons: [], + professionals: [], + invites: [] }; // TODO: get this object from window.activity ? const store = createStore({ @@ -86,14 +88,12 @@ const store = createStore({ // ConcernedGroups addPersonsInvolved(state, payload) { //console.log('### mutation addPersonsInvolved', payload.result.type); - console.log(state) - console.log(payload) switch (payload.result.type) { case 'person': state.activity.persons.push(payload.result); break; case 'thirdparty': - state.activity.thirdParties.push(payload.result); + state.activity.professionals.push(payload.result); break; case 'user': state.activity.users.push(payload.result); @@ -107,7 +107,7 @@ const store = createStore({ state.activity.persons = state.activity.persons.filter(person => person !== payload); break; case 'thirdparty': - state.activity.thirdParties = state.activity.thirdParties.filter(thirdparty => thirdparty !== payload); + state.activity.professionals = state.activity.professionals.filter(thirdparty => thirdparty !== payload); break; case 'user': state.activity.users = state.activity.users.filter(user => user !== payload); @@ -138,18 +138,18 @@ const store = createStore({ commit('updateActionsSelected', payload); }, addPersonsInvolved({ commit }, payload) { - //console.log('### action addPersonsInvolved', payload.result.type); + console.log('### action addPersonsInvolved', payload.result.type); switch (payload.result.type) { case 'person': let aPersons = document.getElementById("chill_calendarbundle_calendar_persons"); aPersons.value = addIdToValue(aPersons.value, payload.result.id); break; case 'thirdparty': - let aThirdParties = document.getElementById("chill_calendarbundle_calendar_thirdParties"); + let aThirdParties = document.getElementById("chill_calendarbundle_calendar_professionals"); aThirdParties.value = addIdToValue(aThirdParties.value, payload.result.id); break; case 'user': - let aUsers = document.getElementById("chill_calendarbundle_calendar_users"); + let aUsers = document.getElementById("chill_calendarbundle_calendar_invites"); aUsers.value = addIdToValue(aUsers.value, payload.result.id); break; }; @@ -163,11 +163,11 @@ const store = createStore({ aPersons.value = removeIdFromValue(aPersons.value, payload.id); break; case 'thirdparty': - let aThirdParties = document.getElementById("chill_calendarbundle_calendar_thirdParties"); + let aThirdParties = document.getElementById("chill_calendarbundle_calendar_professionals"); aThirdParties.value = removeIdFromValue(aThirdParties.value, payload.id); break; case 'user': - let aUsers = document.getElementById("chill_calendarbundle_calendar_users"); + let aUsers = document.getElementById("chill_calendarbundle_calendar_invites"); aUsers.value = removeIdFromValue(aUsers.value, payload.id); break; }; diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/new.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/new.html.twig index 84811aaf4..84b3cc37e 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/new.html.twig +++ b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/new.html.twig @@ -12,6 +12,9 @@ {%- if form.persons is defined -%} {{ form_widget(form.persons) }} {% endif %} +{%- if form.professionals is defined -%} + {{ form_widget(form.professionals) }} +{% endif %} {%- if form.nonProfessionals is defined -%} {{ form_widget(form.nonProfessionals) }} {% endif %} From adc462b7359f5074fda450386c67955de409f44e Mon Sep 17 00:00:00 2001 From: nobohan Date: Mon, 19 Jul 2021 10:13:08 +0200 Subject: [PATCH 11/59] rdv: simplify the vuejs component (removed not used parts) --- .../Resources/public/vuejs/Calendar/store.js | 75 ------------------- 1 file changed, 75 deletions(-) diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js index 2a7ce62f4..c512ed5a0 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js @@ -2,7 +2,6 @@ import 'es6-promise/auto'; import { createStore } from 'vuex'; const debug = process.env.NODE_ENV !== 'production'; -//console.log('window.activity', window.activity); const addIdToValue = (string, id) => { let array = string ? string.split(',') : []; @@ -18,10 +17,8 @@ const removeIdFromValue = (string, id) => { return str; }; - const activity = { accompanyingPeriod: null, - socialIssues: [], persons: [], professionals: [], invites: [] @@ -31,60 +28,9 @@ const store = createStore({ strict: debug, state: { activity: activity, - socialIssuesOther: [], - socialActionsList: [], }, mutations: { - // SocialIssueAcc - addIssueInList(state, issue) { - //console.log('add issue list', issue.id); - state.activity.accompanyingPeriod.socialIssues.push(issue); - }, - addIssueSelected(state, issue) { - //console.log('add issue selected', issue.id); - state.activity.socialIssues.push(issue); - }, - updateIssuesSelected(state, issues) { - //console.log('update issues selected', issues); - state.activity.socialIssues = issues; - }, - updateIssuesOther(state, payload) { - //console.log('update issues other'); - state.socialIssuesOther = payload; - }, - removeIssueInOther(state, issue) { - //console.log('remove issue other', issue.id); - state.socialIssuesOther = state.socialIssuesOther.filter(i => i.id !== issue.id); - }, - resetActionsList(state) { - //console.log('reset list actions'); - state.socialActionsList = []; - }, - addActionInList(state, action) { - //console.log('add action list', action.id); - state.socialActionsList.push(action); - }, - updateActionsSelected(state, actions) { - //console.log('update actions selected', actions); - state.activity.socialActions = actions; - }, - filterList(state, list) { - const filterList = (list) => { - // remove duplicates entries - list = list.filter((value, index) => list.findIndex(array => array.id === value.id) === index); - // alpha sort - list.sort((a,b) => (a.text > b.text) ? 1 : ((b.text > a.text) ? -1 : 0)); - return list; - }; - if (list === 'issues') { - state.activity.accompanyingPeriod.socialIssues = filterList(state.activity.accompanyingPeriod.socialIssues); - } - if (list === 'actions') { - state.socialActionsList = filterList(state.socialActionsList); - } - }, - // ConcernedGroups addPersonsInvolved(state, payload) { //console.log('### mutation addPersonsInvolved', payload.result.type); @@ -116,27 +62,6 @@ const store = createStore({ } }, actions: { - addIssueSelected({ commit }, issue) { - let aSocialIssues = document.getElementById("chill_calendarbundle_calendar_socialIssues"); - aSocialIssues.value = addIdToValue(aSocialIssues.value, issue.id); - commit('addIssueSelected', issue); - }, - updateIssuesSelected({ commit }, payload) { - let aSocialIssues = document.getElementById("chill_calendarbundle_calendar_socialIssues"); - aSocialIssues.value = ''; - payload.forEach(item => { - aSocialIssues.value = addIdToValue(aSocialIssues.value, item.id); - }); - commit('updateIssuesSelected', payload); - }, - updateActionsSelected({ commit }, payload) { - let aSocialActions = document.getElementById("chill_calendarbundle_calendar_socialActions"); - aSocialActions.value = ''; - payload.forEach(item => { - aSocialActions.value = addIdToValue(aSocialActions.value, item.id); - }); - commit('updateActionsSelected', payload); - }, addPersonsInvolved({ commit }, payload) { console.log('### action addPersonsInvolved', payload.result.type); switch (payload.result.type) { From 516c286519bc6360973fb3f798196290786571dd Mon Sep 17 00:00:00 2001 From: nobohan Date: Mon, 19 Jul 2021 10:26:44 +0200 Subject: [PATCH 12/59] rdv: can add thirdparty to a rdv --- .../Resources/public/vuejs/Calendar/store.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js index c512ed5a0..82d7799a1 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js @@ -20,8 +20,10 @@ const removeIdFromValue = (string, id) => { const activity = { accompanyingPeriod: null, persons: [], - professionals: [], - invites: [] + thirdParties: [], + users: [], + //professionals: [], + //invites: [] }; // TODO: get this object from window.activity ? const store = createStore({ @@ -39,7 +41,7 @@ const store = createStore({ state.activity.persons.push(payload.result); break; case 'thirdparty': - state.activity.professionals.push(payload.result); + state.activity.thirdParties.push(payload.result); break; case 'user': state.activity.users.push(payload.result); @@ -53,7 +55,7 @@ const store = createStore({ state.activity.persons = state.activity.persons.filter(person => person !== payload); break; case 'thirdparty': - state.activity.professionals = state.activity.professionals.filter(thirdparty => thirdparty !== payload); + state.activity.thirdParties = state.activity.thirdParties.filter(thirdparty => thirdparty !== payload); break; case 'user': state.activity.users = state.activity.users.filter(user => user !== payload); From 206347de91cc5e8f4ff5d46eaa8e61aeb8224d5b Mon Sep 17 00:00:00 2001 From: nobohan Date: Mon, 19 Jul 2021 11:07:29 +0200 Subject: [PATCH 13/59] rdv: add entity to serialize (WIP) --- .../Controller/CalendarController.php | 7 ++++--- .../Resources/public/vuejs/Calendar/store.js | 18 +++++++++--------- .../Calendar/newAccompanyingCourse.html.twig | 1 + 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php b/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php index 4bde0e6f9..fe090962a 100644 --- a/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php +++ b/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php @@ -190,14 +190,15 @@ class CalendarController extends AbstractController throw $this->createNotFoundException('Template not found'); } - // $activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']); - + $entity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']); + dump($entity_array); + return $this->render($view, [ 'user' => $user, 'accompanyingCourse' => $accompanyingPeriod, 'entity' => $entity, 'form' => $form->createView(), - //'activity_json' => $calendar_array + 'entity_json' => $entity_array ]); } diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js index 82d7799a1..1eff54f8a 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js @@ -17,19 +17,19 @@ const removeIdFromValue = (string, id) => { return str; }; -const activity = { - accompanyingPeriod: null, - persons: [], - thirdParties: [], - users: [], - //professionals: [], - //invites: [] -}; // TODO: get this object from window.activity ? +// const activity = { +// accompanyingPeriod: window.accompanyingPeriod, +// persons: [], +// thirdParties: [], +// users: [] +// }; // TODO: get this object from window.activity ? + +console.log(window.entity) const store = createStore({ strict: debug, state: { - activity: activity, + activity: window.entity, }, mutations: { diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/newAccompanyingCourse.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/newAccompanyingCourse.html.twig index 7d1d27d4c..76f4583ed 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/newAccompanyingCourse.html.twig +++ b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/newAccompanyingCourse.html.twig @@ -25,6 +25,7 @@ chill.displayAlertWhenLeavingUnsubmittedForm('form[name="{{ form.vars.form.vars.name }}"]', '{{ "You are going to leave a page with unsubmitted data. Are you sure you want to leave ?"|trans }}'); }); + window.entity = {{ entity_json|json_encode|raw }}; {{ encore_entry_script_tags('vue_calendar') }} {% endblock %} From 4b8736ae57c82f5db4fff7209606913528cdcb5c Mon Sep 17 00:00:00 2001 From: nobohan Date: Mon, 19 Jul 2021 11:30:06 +0200 Subject: [PATCH 14/59] rdv: fix adding thirdparty when creating a rdv --- .../ChillCalendarBundle/Entity/Calendar.php | 7 ++++++- .../Resources/public/vuejs/Calendar/store.js | 17 ++++++++--------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/Bundle/ChillCalendarBundle/Entity/Calendar.php b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php index 9aacabcb1..d4a906230 100644 --- a/src/Bundle/ChillCalendarBundle/Entity/Calendar.php +++ b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php @@ -2,10 +2,10 @@ namespace Chill\CalendarBundle\Entity; -use Chill\CalendarBundle\Repository\CalendarRepository; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; use Doctrine\Common\Collections\Collection; +use Symfony\Component\Serializer\Annotation\Groups; use Chill\MainBundle\Entity\User; use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\Person; @@ -15,6 +15,7 @@ use Chill\CalendarBundle\Entity\CancelReason; use Chill\CalendarBundle\Entity\CalendarRange; use Chill\CalendarBundle\Entity\Invite; use Chill\ActivityBundle\Entity\Activity; +use Chill\CalendarBundle\Repository\CalendarRepository; /** * @ORM\Table(name="chill_calendar.calendar") @@ -36,6 +37,7 @@ class Calendar /** * @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod") + * @Groups({"read"}) */ private AccompanyingPeriod $accompanyingPeriod; @@ -50,6 +52,7 @@ class Calendar * targetEntity="Chill\PersonBundle\Entity\Person", * cascade={"persist", "remove", "merge", "detach"}) * @ORM\JoinTable(name="chill_calendar.calendar_to_persons") + * @Groups({"read"}) */ private Collection $persons; @@ -68,6 +71,7 @@ class Calendar * targetEntity="Chill\ThirdPartyBundle\Entity\ThirdParty", * cascade={"persist", "remove", "merge", "detach"}) * @ORM\JoinTable(name="chill_calendar.calendar_to_thirdparties") + * @Groups({"read"}) */ private Collection $professionals; @@ -77,6 +81,7 @@ class Calendar * targetEntity="Invite", * cascade={"persist", "remove", "merge", "detach"}) * @ORM\JoinTable(name="chill_calendar.calendar_to_invites") + * @Groups({"read"}) */ private Collection $invites; diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js index 1eff54f8a..99a9da5d8 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js @@ -17,19 +17,18 @@ const removeIdFromValue = (string, id) => { return str; }; -// const activity = { -// accompanyingPeriod: window.accompanyingPeriod, -// persons: [], -// thirdParties: [], -// users: [] -// }; // TODO: get this object from window.activity ? - -console.log(window.entity) +/* +* Assign missing keys for the ConcernedGroups component +*/ +const mapEntity = (entity) => { + Object.assign(entity, {thirdParties: entity.professionals, users: entity.invites}); + return entity; +}; const store = createStore({ strict: debug, state: { - activity: window.entity, + activity: mapEntity(window.entity), }, mutations: { From 227be0b4820380bb4d033d02f4eb29a547b25c36 Mon Sep 17 00:00:00 2001 From: nobohan Date: Mon, 19 Jul 2021 12:06:21 +0200 Subject: [PATCH 15/59] rdv: add default status on rdv when creating a new rdv --- .../Controller/CalendarController.php | 5 +--- .../ChillCalendarBundle/Entity/Calendar.php | 4 +++ .../ChillCalendarBundle/Form/CalendarType.php | 27 ++++++++++++------- .../Resources/config/services/form.yml | 1 + 4 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php b/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php index fe090962a..b84f72d73 100644 --- a/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php +++ b/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php @@ -158,6 +158,7 @@ class CalendarController extends AbstractController $entity = new Calendar(); $entity->setUser($this->getUser()); + $entity->setStatus($entity::STATUS_VALID); // if ($user instanceof User) { // $entity->setPerson($user); @@ -167,9 +168,6 @@ class CalendarController extends AbstractController $entity->setAccompanyingPeriod($accompanyingPeriod); } - // $entity->setType($activityType); - // $entity->setDate(new \DateTime('now')); - $form = $this->createForm(CalendarType::class, $entity, [ 'accompanyingPeriod' => $accompanyingPeriod, ])->handleRequest($request); @@ -191,7 +189,6 @@ class CalendarController extends AbstractController } $entity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']); - dump($entity_array); return $this->render($view, [ 'user' => $user, diff --git a/src/Bundle/ChillCalendarBundle/Entity/Calendar.php b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php index d4a906230..6d898133e 100644 --- a/src/Bundle/ChillCalendarBundle/Entity/Calendar.php +++ b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php @@ -23,6 +23,10 @@ use Chill\CalendarBundle\Repository\CalendarRepository; */ class Calendar { + const STATUS_VALID = 'valid'; + const STATUS_CANCELED = 'canceled'; + const STATUS_MOVED = 'moved'; + /** * @ORM\Id * @ORM\GeneratedValue diff --git a/src/Bundle/ChillCalendarBundle/Form/CalendarType.php b/src/Bundle/ChillCalendarBundle/Form/CalendarType.php index 7500594ea..a4072f12e 100644 --- a/src/Bundle/ChillCalendarBundle/Form/CalendarType.php +++ b/src/Bundle/ChillCalendarBundle/Form/CalendarType.php @@ -8,24 +8,33 @@ use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Form\Extension\Core\Type\DateType; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; +use Symfony\Component\Form\Extension\Core\Type\TextType; +use Doctrine\Persistence\ObjectManager; +use Symfony\Component\Form\CallbackTransformer; +use Symfony\Component\Form\Extension\Core\Type\HiddenType; use Chill\MainBundle\Form\Type\CommentType; use Chill\CalendarBundle\Entity\Calendar; use Chill\CalendarBundle\Entity\CancelReason; +use Chill\CalendarBundle\Entity\Invite; use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\PersonBundle\Entity\Person; use Chill\ThirdPartyBundle\Entity\ThirdParty; -use Symfony\Component\Form\CallbackTransformer; -use Symfony\Component\Form\Extension\Core\Type\HiddenType; + class CalendarType extends AbstractType { - private TranslatableStringHelper $translatableStringHelper; + protected TranslatableStringHelper $translatableStringHelper; + protected ObjectManager $om; - public function __construct(TranslatableStringHelper $translatableStringHelper) + public function __construct( + TranslatableStringHelper $translatableStringHelper, + ObjectManager $om + ) { $this->translatableStringHelper = $translatableStringHelper; + $this->om = $om; } /** @@ -38,12 +47,12 @@ class CalendarType extends AbstractType 'required' => false )) ->add('startDate', DateType::class, array( - 'required' => false, + 'required' => true, 'input' => 'datetime_immutable', 'widget' => 'single_text' )) ->add('endDate', DateType::class, array( - 'required' => false, + 'required' => true, 'input' => 'datetime_immutable', 'widget' => 'single_text' )) @@ -102,8 +111,8 @@ class CalendarType extends AbstractType )) ; - // $builder->add('users', HiddenType::class); - // $builder->get('users') + // $builder->add('invites', HiddenType::class); + // $builder->get('invites') // ->addModelTransformer(new CallbackTransformer( // function (iterable $usersAsIterable): string { // $userIds = []; @@ -114,7 +123,7 @@ class CalendarType extends AbstractType // }, // function (?string $usersAsString): array { // return array_map( - // fn(string $id): ?User => $this->om->getRepository(User::class)->findOneBy(['id' => (int) $id]), + // fn(string $id): ?Invite => $this->om->getRepository(Invite::class)->findOneBy(['id' => (int) $id]), // explode(',', $usersAsString) // ); // } diff --git a/src/Bundle/ChillCalendarBundle/Resources/config/services/form.yml b/src/Bundle/ChillCalendarBundle/Resources/config/services/form.yml index 12241277f..85095dc9a 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/config/services/form.yml +++ b/src/Bundle/ChillCalendarBundle/Resources/config/services/form.yml @@ -4,6 +4,7 @@ services: class: Chill\CalendarBundle\Form\CalendarType arguments: - "@chill.main.helper.translatable_string" + - "@doctrine.orm.entity_manager" tags: - { name: form.type, alias: chill_calendarbundle_calendar } \ No newline at end of file From 3c378028210b7b8483ad1974858e2798decef78d Mon Sep 17 00:00:00 2001 From: nobohan Date: Mon, 19 Jul 2021 13:59:50 +0200 Subject: [PATCH 16/59] rdv: add show calendar --- .../Controller/CalendarController.php | 315 ++++++++---------- .../ChillCalendarBundle/Entity/Calendar.php | 28 ++ .../Resources/views/Calendar/new.html.twig | 4 - .../Resources/views/Calendar/show.html.twig | 75 +++++ .../Calendar/showAccompanyingCourse.html.twig | 15 + 5 files changed, 266 insertions(+), 171 deletions(-) create mode 100644 src/Bundle/ChillCalendarBundle/Resources/views/Calendar/show.html.twig create mode 100644 src/Bundle/ChillCalendarBundle/Resources/views/Calendar/showAccompanyingCourse.html.twig diff --git a/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php b/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php index b84f72d73..b9952a45d 100644 --- a/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php +++ b/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php @@ -199,213 +199,194 @@ class CalendarController extends AbstractController ]); } - // public function showAction(Request $request, $id): Response - // { - // $em = $this->getDoctrine()->getManager(); + /** + * Show a calendar item + * @Route("/{_locale}/calendar/{id}/show", name="chill_calendar_calendar_show") + */ + public function showAction(Request $request, $id): Response + { + $em = $this->getDoctrine()->getManager(); - // [$person, $accompanyingPeriod] = $this->getEntity($request); + [$user, $accompanyingPeriod] = $this->getEntity($request); - // if ($accompanyingPeriod instanceof AccompanyingPeriod) { - // $view = 'ChillCalendarBundle:Calendar:showAccompanyingCourse.html.twig'; - // } elseif ($person instanceof Person) { - // $view = 'ChillCalendarBundle:Calendar:showPerson.html.twig'; - // } + if ($accompanyingPeriod instanceof AccompanyingPeriod) { + $view = 'ChillCalendarBundle:Calendar:showAccompanyingCourse.html.twig'; + } + // elseif ($person instanceof Person) { + // $view = 'ChillCalendarBundle:Calendar:showPerson.html.twig'; + // } - // $entity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id); + $entity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id); - // if (!$entity) { - // throw $this->createNotFoundException('Unable to find Calendar entity.'); - // } + if (!$entity) { + throw $this->createNotFoundException('Unable to find Calendar entity.'); + } - // if (null !== $accompanyingPeriod) { - // $entity->personsAssociated = $entity->getPersonsAssociated(); - // $entity->personsNotAssociated = $entity->getPersonsNotAssociated(); - // } + if (null !== $accompanyingPeriod) { + $entity->personsAssociated = $entity->getPersonsAssociated(); + $entity->personsNotAssociated = $entity->getPersonsNotAssociated(); + } - // // TODO revoir le Voter de Activity pour tenir compte qu'une activité peut appartenir a une période - // // $this->denyAccessUnlessGranted('CHILL_ACTIVITY_SEE', $entity); + // $deleteForm = $this->createDeleteForm($id, $accompanyingPeriod); - // $deleteForm = $this->createDeleteForm($id, $person, $accompanyingPeriod); + if ($view === null) { + throw $this->createNotFoundException('Template not found'); + } - // // TODO - // /* - // $event = new PrivacyEvent($person, array( - // 'element_class' => Activity::class, - // 'element_id' => $entity->getId(), - // 'action' => 'show' - // )); - // $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); - // */ + return $this->render($view, array( + //'person' => $person, + 'accompanyingCourse' => $accompanyingPeriod, + 'entity' => $entity, + //'delete_form' => $deleteForm->createView(), + )); + } - // if ($view === null) { - // throw $this->createNotFoundException('Template not found'); - // } - // return $this->render($view, array( - // 'person' => $person, - // 'accompanyingCourse' => $accompanyingPeriod, - // 'entity' => $entity, - // 'delete_form' => $deleteForm->createView(), - // )); - // } - // /** - // * Displays a form to edit an existing Activity entity. - // * - // */ - // public function editAction($id, Request $request): Response - // { - // $em = $this->getDoctrine()->getManager(); + /** + * Edit a calendar item + * @Route("/{_locale}/calendar/{id}/edit", name="chill_calendar_calendar_edit") + */ + public function editAction($id, Request $request): Response + { + $em = $this->getDoctrine()->getManager(); - // [$person, $accompanyingPeriod] = $this->getEntity($request); + [$person, $accompanyingPeriod] = $this->getEntity($request); - // if ($accompanyingPeriod instanceof AccompanyingPeriod) { - // $view = 'ChillCalendarBundle:Calendar:editAccompanyingCourse.html.twig'; - // } elseif ($person instanceof Person) { - // $view = 'ChillCalendarBundle:Calendar:editPerson.html.twig'; - // } + if ($accompanyingPeriod instanceof AccompanyingPeriod) { + $view = 'ChillCalendarBundle:Calendar:editAccompanyingCourse.html.twig'; + } + // elseif ($person instanceof Person) { + // $view = 'ChillCalendarBundle:Calendar:editPerson.html.twig'; + // } - // $entity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id); + $entity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id); - // if (!$entity) { - // throw $this->createNotFoundException('Unable to find Calendar entity.'); - // } + if (!$entity) { + throw $this->createNotFoundException('Unable to find Calendar entity.'); + } - // // TODO - // // $this->denyAccessUnlessGranted('CHILL_ACTIVITY_UPDATE', $entity); + $form = $this->createForm(CalendarType::class, $entity, [ + 'center' => $entity->getCenter(), + 'role' => new Role('CHILL_ACTIVITY_UPDATE'), + 'activityType' => $entity->getType(), + 'accompanyingPeriod' => $accompanyingPeriod, + ])->handleRequest($request); - // $form = $this->createForm(CalendarType::class, $entity, [ - // 'center' => $entity->getCenter(), - // 'role' => new Role('CHILL_ACTIVITY_UPDATE'), - // 'activityType' => $entity->getType(), - // 'accompanyingPeriod' => $accompanyingPeriod, - // ])->handleRequest($request); + if ($form->isSubmitted() && $form->isValid()) { + $em->persist($entity); + $em->flush(); - // if ($form->isSubmitted() && $form->isValid()) { - // $em->persist($entity); - // $em->flush(); + $this->addFlash('success', $this->get('translator')->trans('Success : activity updated!')); - // $this->addFlash('success', $this->get('translator')->trans('Success : activity updated!')); + $params = $this->buildParamsToUrl($person, $accompanyingPeriod); + $params['id'] = $id; + return $this->redirectToRoute('chill_activity_activity_show', $params); + } - // $params = $this->buildParamsToUrl($person, $accompanyingPeriod); - // $params['id'] = $id; - // return $this->redirectToRoute('chill_activity_activity_show', $params); - // } + $deleteForm = $this->createDeleteForm($id, $person, $accompanyingPeriod); - // $deleteForm = $this->createDeleteForm($id, $person, $accompanyingPeriod); + if ($view === null) { + throw $this->createNotFoundException('Template not found'); + } - // /* - // * TODO - // $event = new PrivacyEvent($person, array( - // 'element_class' => Calendar::class, - // 'element_id' => $entity->getId(), - // 'action' => 'edit' - // )); - // $this->eventDispatcher->dispatch(PrivacyEvent::PERSON_PRIVACY_EVENT, $event); - // */ + $activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']); - // if ($view === null) { - // throw $this->createNotFoundException('Template not found'); - // } + return $this->render($view, array( + 'entity' => $entity, + 'edit_form' => $form->createView(), + 'delete_form' => $deleteForm->createView(), + 'accompanyingCourse' => $accompanyingPeriod, + 'activity_json' => $activity_array + )); + } - // $activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']); + /** + * Delete a calendar item + * @Route("/{_locale}/calendar/{id}/delete", name="chill_calendar_calendar_delete") + */ + public function deleteAction(Request $request, $id) + { + $em = $this->getDoctrine()->getManager(); - // return $this->render($view, array( - // 'entity' => $entity, - // 'edit_form' => $form->createView(), - // 'delete_form' => $deleteForm->createView(), - // 'person' => $person, - // 'accompanyingCourse' => $accompanyingPeriod, - // 'activity_json' => $activity_array - // )); - // } + [$person, $accompanyingPeriod] = $this->getEntity($request); - // /** - // * Deletes a Calendar entity. - // * - // */ - // public function deleteAction(Request $request, $id) - // { - // $em = $this->getDoctrine()->getManager(); + if ($accompanyingPeriod instanceof AccompanyingPeriod) { + $view = 'ChillCalendarBundle:Calendar:confirm_deleteAccompanyingCourse.html.twig'; + } elseif ($person instanceof Person) { + $view = 'ChillCalendarBundle:Calendar:confirm_deletePerson.html.twig'; + } - // [$person, $accompanyingPeriod] = $this->getEntity($request); + /* @var $activity Calendar */ + $activity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id); - // if ($accompanyingPeriod instanceof AccompanyingPeriod) { - // $view = 'ChillCalendarBundle:Calendar:confirm_deleteAccompanyingCourse.html.twig'; - // } elseif ($person instanceof Person) { - // $view = 'ChillCalendarBundle:Calendar:confirm_deletePerson.html.twig'; - // } + if (!$activity) { + throw $this->createNotFoundException('Unable to find Calendar entity.'); + } - // /* @var $activity Calendar */ - // $activity = $em->getRepository('ChillCalendarBundle:Calendar')->find($id); + // TODO + // $this->denyAccessUnlessGranted('CHILL_ACTIVITY_DELETE', $activity); - // if (!$activity) { - // throw $this->createNotFoundException('Unable to find Calendar entity.'); - // } + $form = $this->createDeleteForm($id, $person, $accompanyingPeriod); - // // TODO - // // $this->denyAccessUnlessGranted('CHILL_ACTIVITY_DELETE', $activity); + if ($request->getMethod() === Request::METHOD_DELETE) { + $form->handleRequest($request); - // $form = $this->createDeleteForm($id, $person, $accompanyingPeriod); + if ($form->isValid()) { - // if ($request->getMethod() === Request::METHOD_DELETE) { - // $form->handleRequest($request); + $this->logger->notice("An activity has been removed", array( + 'by_user' => $this->getUser()->getUsername(), + 'activity_id' => $activity->getId(), + 'person_id' => $activity->getPerson() ? $activity->getPerson()->getId() : null, + 'comment' => $activity->getComment()->getComment(), + 'scope_id' => $activity->getScope() ? $activity->getScope()->getId() : null, + 'reasons_ids' => $activity->getReasons() + ->map(function ($ar) { return $ar->getId(); }) + ->toArray(), + 'type_id' => $activity->getType()->getId(), + 'duration' => $activity->getDurationTime() ? $activity->getDurationTime()->format('U') : null, + 'date' => $activity->getDate()->format('Y-m-d'), + 'attendee' => $activity->getAttendee() + )); - // if ($form->isValid()) { + $em->remove($activity); + $em->flush(); - // $this->logger->notice("An activity has been removed", array( - // 'by_user' => $this->getUser()->getUsername(), - // 'activity_id' => $activity->getId(), - // 'person_id' => $activity->getPerson() ? $activity->getPerson()->getId() : null, - // 'comment' => $activity->getComment()->getComment(), - // 'scope_id' => $activity->getScope() ? $activity->getScope()->getId() : null, - // 'reasons_ids' => $activity->getReasons() - // ->map(function ($ar) { return $ar->getId(); }) - // ->toArray(), - // 'type_id' => $activity->getType()->getId(), - // 'duration' => $activity->getDurationTime() ? $activity->getDurationTime()->format('U') : null, - // 'date' => $activity->getDate()->format('Y-m-d'), - // 'attendee' => $activity->getAttendee() - // )); + $this->addFlash('success', $this->get('translator') + ->trans("The activity has been successfully removed.")); - // $em->remove($activity); - // $em->flush(); + $params = $this->buildParamsToUrl($person, $accompanyingPeriod); + return $this->redirectToRoute('chill_activity_activity_list', $params); + } + } - // $this->addFlash('success', $this->get('translator') - // ->trans("The activity has been successfully removed.")); + if ($view === null) { + throw $this->createNotFoundException('Template not found'); + } - // $params = $this->buildParamsToUrl($person, $accompanyingPeriod); - // return $this->redirectToRoute('chill_activity_activity_list', $params); - // } - // } + return $this->render($view, array( + 'activity' => $activity, + 'delete_form' => $form->createView(), + 'person' => $person, + 'accompanyingCourse' => $accompanyingPeriod, + )); + } - // if ($view === null) { - // throw $this->createNotFoundException('Template not found'); - // } + /** + * Creates a form to delete a Calendar entity by id. + */ + private function createDeleteForm(int $id, ?Person $person, ?AccompanyingPeriod $accompanyingPeriod): Form + { + $params = $this->buildParamsToUrl($person, $accompanyingPeriod); + $params['id'] = $id; - // return $this->render($view, array( - // 'activity' => $activity, - // 'delete_form' => $form->createView(), - // 'person' => $person, - // 'accompanyingCourse' => $accompanyingPeriod, - // )); - // } - - // /** - // * Creates a form to delete a Calendar entity by id. - // */ - // private function createDeleteForm(int $id, ?Person $person, ?AccompanyingPeriod $accompanyingPeriod): Form - // { - // $params = $this->buildParamsToUrl($person, $accompanyingPeriod); - // $params['id'] = $id; - - // return $this->createFormBuilder() - // ->setAction($this->generateUrl('chill_activity_activity_delete', $params)) - // ->setMethod('DELETE') - // ->add('submit', SubmitType::class, array('label' => 'Delete')) - // ->getForm() - // ; - // } + return $this->createFormBuilder() + ->setAction($this->generateUrl('chill_activity_activity_delete', $params)) + ->setMethod('DELETE') + ->add('submit', SubmitType::class, array('label' => 'Delete')) + ->getForm() + ; + } private function getEntity(Request $request): array { diff --git a/src/Bundle/ChillCalendarBundle/Entity/Calendar.php b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php index 6d898133e..508279664 100644 --- a/src/Bundle/ChillCalendarBundle/Entity/Calendar.php +++ b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php @@ -373,4 +373,32 @@ class Calendar return $this; } + + public function getPersonsAssociated(): array + { + if (null !== $this->accompanyingPeriod) { + $personsAssociated = []; + foreach ($this->accompanyingPeriod->getParticipations() as $participation) { + if ($this->persons->contains($participation->getPerson())) { + $personsAssociated[] = $participation->getPerson(); + } + } + return $personsAssociated; + } + return []; + } + + public function getPersonsNotAssociated(): array + { + if (null !== $this->accompanyingPeriod) { + $personsNotAssociated = []; + foreach ($this->persons as $person) { + if (!in_array($person, $this->getPersonsAssociated())) { + $personsNotAssociated[] = $person; + } + } + return $personsNotAssociated; + } + return []; + } } diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/new.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/new.html.twig index 84b3cc37e..58f20230e 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/new.html.twig +++ b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/new.html.twig @@ -36,10 +36,6 @@ .. location -{%- if form.status is defined -%} - {{ form_row(form.status) }} -{% endif %} - {%- if form.cancelReason is defined -%} {{ form_row(form.cancelReason) }} {% endif %} diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/show.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/show.html.twig new file mode 100644 index 000000000..95af5c686 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/show.html.twig @@ -0,0 +1,75 @@ +

{{ "Calendar"|trans }}

+ +
+ +
+ + +

{{ 'Calendar data'|trans }}

+ +
{{ 'start date'|trans }}
+
{{ entity.startDate|format_date('long') }}
+ +
{{ 'end date'|trans }}
+
{{ entity.endDate|format_date('long') }}
+ +
{{ 'cancel reason'|trans }}
+
+ {% if entity.cancelReason is not null %} + {{ entity.cancelReason }} + {% else %} + {{ 'Unknown'|trans }} + {% endif %} +
+ +
{{ 'status'|trans }}
+
{{ entity.status }}
+ + {% if not entity.comment.isEmpty %} +
{{ 'calendar comment'|trans }}
+
{{ entity.comment|chill_entity_render_box }}
+ {% endif %} + +
{{ 'sendSMS'|trans }}
+
+ {% if entity.sendSMS is not null %} + {% if entity.sendSMS %}Oui{% else %}Non{% endif %} + {% else %} + {{ 'Unknown'|trans }} + {% endif %} +
+ + + + +{% set accompanying_course_id = null %} +{% if accompanyingCourse %} + {% set accompanying_course_id = accompanyingCourse.id %} +{% endif %} + + diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/showAccompanyingCourse.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/showAccompanyingCourse.html.twig new file mode 100644 index 000000000..587d764b8 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/showAccompanyingCourse.html.twig @@ -0,0 +1,15 @@ +{% extends "@ChillPerson/AccompanyingCourse/layout.html.twig" %} + +{% set activeRouteKey = 'chill_calendar_calendar_list' %} + +{% block title 'Calendar'|trans %} + +{% block content -%} +
+
+
+ {% include 'ChillCalendarBundle:Calendar:show.html.twig' with {'context': 'accompanyingCourse'} %} +
+
+
+{% endblock content %} From d542f582e639b42851b69103b41a1e1d908a24ec Mon Sep 17 00:00:00 2001 From: nobohan Date: Mon, 19 Jul 2021 15:22:36 +0200 Subject: [PATCH 17/59] rdv: allow null concerned persons in form --- .../ChillCalendarBundle/Entity/Calendar.php | 31 +++++++++++++------ .../Resources/views/Calendar/show.html.twig | 3 ++ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/Bundle/ChillCalendarBundle/Entity/Calendar.php b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php index 508279664..ca3b4b25b 100644 --- a/src/Bundle/ChillCalendarBundle/Entity/Calendar.php +++ b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php @@ -58,7 +58,7 @@ class Calendar * @ORM\JoinTable(name="chill_calendar.calendar_to_persons") * @Groups({"read"}) */ - private Collection $persons; + private ?Collection $persons = null; /** * @@ -67,7 +67,7 @@ class Calendar * cascade={"persist", "remove", "merge", "detach"}) * @ORM\JoinTable(name="chill_calendar.calendar_to_non_professionals") */ - private Collection $nonProfessionals; + private ?Collection $nonProfessionals = null; /** * @@ -77,7 +77,7 @@ class Calendar * @ORM\JoinTable(name="chill_calendar.calendar_to_thirdparties") * @Groups({"read"}) */ - private Collection $professionals; + private ?Collection $professionals = null; /** * @@ -87,7 +87,7 @@ class Calendar * @ORM\JoinTable(name="chill_calendar.calendar_to_invites") * @Groups({"read"}) */ - private Collection $invites; + private ?Collection $invites = null; /** * @ORM\Embedded(class=CommentEmbeddable::class, columnPrefix="comment_") @@ -250,9 +250,9 @@ class Calendar return $this->persons; } - public function addPerson(Person $person): self + public function addPerson(?Person $person): self { - if (!$this->persons->contains($person)) { + if (null !== $person) { $this->persons[] = $person; } @@ -298,9 +298,9 @@ class Calendar return $this->professionals; } - public function addProfessional(ThirdParty $professional): self + public function addProfessional(?ThirdParty $professional): self { - if (!$this->professionals->contains($professional)) { + if (null !== $professional) { $this->professionals[] = $professional; } @@ -322,9 +322,9 @@ class Calendar return $this->invites; } - public function addInvite(Invite $invite): self + public function addInvite(?Invite $invite): self { - if (!$this->invites->contains($invite)) { + if (null !== $invite) { $this->invites[] = $invite; } @@ -401,4 +401,15 @@ class Calendar } return []; } + + + public function getThirdParties(): Collection + { + return $this->getProfessionals(); + } + + public function getusers(): Collection + { + return $this->getInvites(); //TODO get users of the invite + } } diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/show.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/show.html.twig index 95af5c686..3617bb3c7 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/show.html.twig +++ b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/show.html.twig @@ -4,6 +4,9 @@ +

{{ 'Concerned groups'|trans }}

+{% include 'ChillActivityBundle:Activity:concernedGroups.html.twig' with {'context': context, 'with_display': 'bloc' } %} +

{{ 'Calendar data'|trans }}

From d4ec5d137e6704fda54fbdf8832612315fb7146d Mon Sep 17 00:00:00 2001 From: nobohan Date: Mon, 19 Jul 2021 16:15:52 +0200 Subject: [PATCH 18/59] rdv: add validation --- .../ChillCalendarBundle/Entity/Calendar.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/Bundle/ChillCalendarBundle/Entity/Calendar.php b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php index ca3b4b25b..85130df98 100644 --- a/src/Bundle/ChillCalendarBundle/Entity/Calendar.php +++ b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php @@ -16,6 +16,9 @@ use Chill\CalendarBundle\Entity\CalendarRange; use Chill\CalendarBundle\Entity\Invite; use Chill\ActivityBundle\Entity\Activity; use Chill\CalendarBundle\Repository\CalendarRepository; +use Symfony\Component\Validator\Constraints\NotBlank; +use Symfony\Component\Validator\Constraints\Range; +use Symfony\Component\Validator\Mapping\ClassMetadata; /** * @ORM\Table(name="chill_calendar.calendar") @@ -412,4 +415,20 @@ class Calendar { return $this->getInvites(); //TODO get users of the invite } + + + public static function loadValidatorMetadata(ClassMetadata $metadata): void + { + $metadata->addPropertyConstraint('startDate', new NotBlank()); + $metadata->addPropertyConstraint('startDate', new Range([ + 'min' => '2 years ago', + 'max' => '+ 2 years', + ])); + $metadata->addPropertyConstraint('endDate', new NotBlank()); + $metadata->addPropertyConstraint('endDate', new Range([ + 'min' => '2 years ago', + 'max' => '+ 2 years', + ])); + } + } From 7e02b284ca75ff1610c1879172237f809e7afe00 Mon Sep 17 00:00:00 2001 From: nobohan Date: Mon, 19 Jul 2021 17:18:56 +0200 Subject: [PATCH 19/59] rdv: others pages: edit, list --- .../Controller/CalendarController.php | 58 ++---------- .../ChillCalendarBundle/Entity/Calendar.php | 5 +- .../ChillCalendarBundle/Form/CalendarType.php | 9 ++ .../Resources/views/Calendar/edit.html.twig | 76 ++++++++++++++++ .../Calendar/editAccompanyingCourse.html.twig | 37 ++++++++ .../Resources/views/Calendar/list.html.twig | 90 +++++-------------- .../Resources/views/Calendar/new.html.twig | 2 +- .../Resources/views/Calendar/show.html.twig | 5 +- 8 files changed, 157 insertions(+), 125 deletions(-) create mode 100644 src/Bundle/ChillCalendarBundle/Resources/views/Calendar/edit.html.twig create mode 100644 src/Bundle/ChillCalendarBundle/Resources/views/Calendar/editAccompanyingCourse.html.twig diff --git a/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php b/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php index b9952a45d..c59b6d5e6 100644 --- a/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php +++ b/src/Bundle/ChillCalendarBundle/Controller/CalendarController.php @@ -100,45 +100,6 @@ class CalendarController extends AbstractController )); } - // public function selectTypeAction(Request $request): Response - // { - // $em = $this->getDoctrine()->getManager(); - // $view = null; - - // [$person, $accompanyingPeriod] = $this->getEntity($request); - - // if ($accompanyingPeriod instanceof AccompanyingPeriod) { - // $view = 'ChillCalendarBundle:Calendar:selectTypeAccompanyingCourse.html.twig'; - // } elseif ($person instanceof Person) { - // $view = 'ChillCalendarBundle:Calendar:selectTypePerson.html.twig'; - // } - - // $data = []; - - // $activityTypeCategories = $em->getRepository(\Chill\CalendarBundle\Entity\ActivityTypeCategory::class) - // ->findBy(['active' => true], ['ordering' => 'ASC']); - - // foreach ($activityTypeCategories as $activityTypeCategory) { - // $activityTypes = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityType::class) - // ->findBy(['active' => true, 'category' => $activityTypeCategory], ['ordering' => 'ASC']); - - // $data[] = [ - // 'activityTypeCategory' => $activityTypeCategory, - // 'activityTypes' => $activityTypes, - // ]; - // } - - // if ($view === null) { - // throw $this->createNotFoundException('Template not found'); - // } - - // return $this->render($view, [ - // 'person' => $person, - // 'accompanyingCourse' => $accompanyingPeriod, - // 'data' => $data, - // ]); - // } - /** * Create a new calendar item * @Route("/{_locale}/calendar/new", name="chill_calendar_calendar_new") @@ -251,7 +212,7 @@ class CalendarController extends AbstractController { $em = $this->getDoctrine()->getManager(); - [$person, $accompanyingPeriod] = $this->getEntity($request); + [$user, $accompanyingPeriod] = $this->getEntity($request); if ($accompanyingPeriod instanceof AccompanyingPeriod) { $view = 'ChillCalendarBundle:Calendar:editAccompanyingCourse.html.twig'; @@ -267,9 +228,6 @@ class CalendarController extends AbstractController } $form = $this->createForm(CalendarType::class, $entity, [ - 'center' => $entity->getCenter(), - 'role' => new Role('CHILL_ACTIVITY_UPDATE'), - 'activityType' => $entity->getType(), 'accompanyingPeriod' => $accompanyingPeriod, ])->handleRequest($request); @@ -279,25 +237,25 @@ class CalendarController extends AbstractController $this->addFlash('success', $this->get('translator')->trans('Success : activity updated!')); - $params = $this->buildParamsToUrl($person, $accompanyingPeriod); + $params = $this->buildParamsToUrl($user, $accompanyingPeriod); $params['id'] = $id; return $this->redirectToRoute('chill_activity_activity_show', $params); } - $deleteForm = $this->createDeleteForm($id, $person, $accompanyingPeriod); + $deleteForm = $this->createDeleteForm($id, $user, $accompanyingPeriod); if ($view === null) { throw $this->createNotFoundException('Template not found'); } - $activity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']); - + $entity_array = $this->serializer->normalize($entity, 'json', ['groups' => 'read']); + return $this->render($view, array( - 'entity' => $entity, - 'edit_form' => $form->createView(), + 'entity' => $entity, + 'form' => $form->createView(), 'delete_form' => $deleteForm->createView(), 'accompanyingCourse' => $accompanyingPeriod, - 'activity_json' => $activity_array + 'entity_json' => $entity_array )); } diff --git a/src/Bundle/ChillCalendarBundle/Entity/Calendar.php b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php index 85130df98..8a106efbd 100644 --- a/src/Bundle/ChillCalendarBundle/Entity/Calendar.php +++ b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php @@ -16,6 +16,8 @@ use Chill\CalendarBundle\Entity\CalendarRange; use Chill\CalendarBundle\Entity\Invite; use Chill\ActivityBundle\Entity\Activity; use Chill\CalendarBundle\Repository\CalendarRepository; +use DateInterval; +use DateTimeImmutable; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\Range; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -51,7 +53,7 @@ class Calendar /** * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User") */ - private User $mainUser; + private ?User $mainUser; /** * @@ -416,7 +418,6 @@ class Calendar return $this->getInvites(); //TODO get users of the invite } - public static function loadValidatorMetadata(ClassMetadata $metadata): void { $metadata->addPropertyConstraint('startDate', new NotBlank()); diff --git a/src/Bundle/ChillCalendarBundle/Form/CalendarType.php b/src/Bundle/ChillCalendarBundle/Form/CalendarType.php index a4072f12e..00b410f7f 100644 --- a/src/Bundle/ChillCalendarBundle/Form/CalendarType.php +++ b/src/Bundle/ChillCalendarBundle/Form/CalendarType.php @@ -17,6 +17,7 @@ use Chill\MainBundle\Form\Type\CommentType; use Chill\CalendarBundle\Entity\Calendar; use Chill\CalendarBundle\Entity\CancelReason; use Chill\CalendarBundle\Entity\Invite; +use Chill\MainBundle\Entity\User; use Chill\MainBundle\Templating\TranslatableStringHelper; use Chill\PersonBundle\Entity\Person; use Chill\ThirdPartyBundle\Entity\ThirdParty; @@ -43,6 +44,14 @@ class CalendarType extends AbstractType public function buildForm(FormBuilderInterface $builder, array $options) { $builder + ->add('mainUser', EntityType::class, array( + 'required' => true, + 'class' => User::class, + 'choice_label' => function (User $entity) { + return $entity->getUsernameCanonical(); + }, + // TODO 'empty_data' => + )) ->add('comment', CommentType::class, array( 'required' => false )) diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/edit.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/edit.html.twig new file mode 100644 index 000000000..c8f869902 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/edit.html.twig @@ -0,0 +1,76 @@ +

{{ "Update calendar"|trans }}

+ +{{ form_start(form) }} +{{ form_errors(form) }} + +{%- if form.mainUser is defined -%} + {{ form_row(form.mainUser) }} +{% endif %} + +

{{ 'Concerned groups'|trans }}

+ +{%- if form.persons is defined -%} + {{ form_widget(form.persons) }} +{% endif %} +{%- if form.professionals is defined -%} + {{ form_widget(form.professionals) }} +{% endif %} +{%- if form.nonProfessionals is defined -%} + {{ form_widget(form.nonProfessionals) }} +{% endif %} +{%- if form.users is defined -%} + {{ form_widget(form.users) }} +{% endif %} + +
+ +

{{ 'Calendar data'|trans }}

+ +{%- if form.startDate is defined -%} + {{ form_row(form.startDate) }} +{% endif %} + +{%- if form.endDate is defined -%} + {{ form_row(form.endDate) }} +{% endif %} + +.. location + +{%- if form.cancelReason is defined -%} + {{ form_row(form.cancelReason) }} +{% endif %} + +{%- if form.comment is defined -%} + {{ form_row(form.comment) }} +{% endif %} + +{%- if form.sendSMS is defined -%} + {{ form_row(form.sendSMS) }} +{% endif %} + + +..calendarRange + + + + +{{ form_end(form) }} + diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/editAccompanyingCourse.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/editAccompanyingCourse.html.twig new file mode 100644 index 000000000..06189c4db --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/editAccompanyingCourse.html.twig @@ -0,0 +1,37 @@ +{% extends "@ChillPerson/AccompanyingCourse/layout.html.twig" %} + +{% set activeRouteKey = 'chill_calendar_calendar_list' %} + +{% block title 'Update calendar'|trans %} + +{% block content %} +
+
+
+ +
{# <=== vue component #} + {% include 'ChillCalendarBundle:Calendar:edit.html.twig' with {'context': 'accompanyingCourse'} %} + +
+
+
+{% endblock %} + +{% block js %} + {{ parent() }} + {{ encore_entry_link_tags('async_upload') }} + + {{ encore_entry_script_tags('vue_calendar') }} +{% endblock %} + +{% block css %} + {{ parent() }} + {{ encore_entry_link_tags('async_upload') }} + {{ encore_entry_link_tags('vue_calendar') }} +{% endblock %} diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/list.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/list.html.twig index 94b5f772b..7b2f1a104 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/list.html.twig +++ b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/list.html.twig @@ -21,31 +21,22 @@ {% for calendar in calendarItems %} - - {% set t = calendar.type %}
- {% if calendar.date %} -

{{ calendar.date|format_date('long') }}

+ {% if calendar.startDate %} +

{{ calendar.startDate|format_date('long') }}

{% endif %} -
- {% if t.durationTimeVisible > 0 %} -

- - {{ calendar.durationTime|date('H:i') }} -

- {% endif %} - - {% if calendar.travelTime and t.travelTimeVisible %} -

- - {{ calendar.travelTime|date('H:i') }} -

- {% endif %} -
+ {% if calendar.endDate %} +

{{ calendar.endDate|format_date('long') }}

+ {% endif %} + + + +

{{ calendar.endDate.diff(calendar.startDate)|date("%i'%s''") }}

+ {% if context == 'user' and calendar.accompanyingPeriod is not empty %}
    - {% if calendar.user and t.userVisible %} + {% if calendar.user %}
  • {{ 'by'|trans }}{{ calendar.user.usernameCanonical }}
  • {% endif %} + {% if calendar.mainUser is not empty %}
  • - {{ calendar.type.name | localize_translatable_string }} - - {% if calendar.attendee is not null and t.attendeeVisible %} - {% if calendar.attendee %} - {{ '→ ' ~ 'present'|trans|capitalize }} - {% else %} - {{ '→ ' ~ 'not present'|trans|capitalize }} - {% endif %} - {% endif %} + {{ 'main user concerned'|trans }}{{ calendar.mainUser.usernameCanonical }}
  • - + {% endif %} + +
  • - {{ 'location'|trans ~ ': ' }} - Domicile de l'usager - {# - {% if calendar.location %}{{ calendar.location }}{% endif %} - #} -
  • - - {%- if t.reasonsVisible -%} -
  • - {%- if calendar.reasons is empty -%} - {{ 'No reason associated'|trans }} + {%- if calendar.comment.isEmpty -%} + {{ 'No comments'|trans }} {%- else -%} - {% for r in calendar.reasons %} - {{ r|chill_entity_render_box }} - {% endfor %} + {{ calendar.comment|chill_entity_render_box }} {%- endif -%}
  • - {% endif %} - - {%- if t.socialIssuesVisible %} - - {% endif %} - {%- if t.socialActionsVisible -%} - - {% endif %} -
From 4a6914be22eb1327929ef79c4845788d7bf99dcd Mon Sep 17 00:00:00 2001 From: nobohan Date: Fri, 23 Jul 2021 16:25:05 +0200 Subject: [PATCH 35/59] rdv: use datetime instead of date fields --- .../ChillCalendarBundle/Entity/Calendar.php | 4 +- .../Resources/views/Calendar/show.html.twig | 4 +- .../migrations/Version20210723142003.php | 39 +++++++++++++++++++ 3 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 src/Bundle/ChillCalendarBundle/migrations/Version20210723142003.php diff --git a/src/Bundle/ChillCalendarBundle/Entity/Calendar.php b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php index 618b354b7..3ee5bcc54 100644 --- a/src/Bundle/ChillCalendarBundle/Entity/Calendar.php +++ b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php @@ -91,12 +91,12 @@ class Calendar private CommentEmbeddable $comment; /** - * @ORM\Column(type="date_immutable") + * @ORM\Column(type="datetimetz_immutable") */ private \DateTimeImmutable $startDate; /** - * @ORM\Column(type="date_immutable") + * @ORM\Column(type="datetimetz_immutable") */ private \DateTimeImmutable $endDate; diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/show.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/show.html.twig index 2674573dc..f6df7ccdf 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/show.html.twig +++ b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/show.html.twig @@ -12,10 +12,10 @@

{{ 'Calendar data'|trans }}

{{ 'start date'|trans }}
-
{{ entity.startDate|format_date('long') }}
+
{{ entity.startDate|format_datetime('long') }}
{{ 'end date'|trans }}
-
{{ entity.endDate|format_date('long') }}
+
{{ entity.endDate|format_datetime('long') }}
{{ 'cancel reason'|trans }}
diff --git a/src/Bundle/ChillCalendarBundle/migrations/Version20210723142003.php b/src/Bundle/ChillCalendarBundle/migrations/Version20210723142003.php new file mode 100644 index 000000000..0af4fb1b8 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/migrations/Version20210723142003.php @@ -0,0 +1,39 @@ +addSql('ALTER TABLE chill_calendar.calendar ALTER startdate TYPE TIMESTAMP(0) WITH TIME ZONE'); + $this->addSql('ALTER TABLE chill_calendar.calendar ALTER startdate DROP DEFAULT'); + $this->addSql('ALTER TABLE chill_calendar.calendar ALTER enddate TYPE TIMESTAMP(0) WITH TIME ZONE'); + $this->addSql('ALTER TABLE chill_calendar.calendar ALTER enddate DROP DEFAULT'); + $this->addSql('COMMENT ON COLUMN chill_calendar.calendar.startDate IS \'(DC2Type:datetimetz_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_calendar.calendar.endDate IS \'(DC2Type:datetimetz_immutable)\''); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE chill_calendar.calendar ALTER startDate TYPE DATE'); + $this->addSql('ALTER TABLE chill_calendar.calendar ALTER startDate DROP DEFAULT'); + $this->addSql('ALTER TABLE chill_calendar.calendar ALTER endDate TYPE DATE'); + $this->addSql('ALTER TABLE chill_calendar.calendar ALTER endDate DROP DEFAULT'); + $this->addSql('COMMENT ON COLUMN chill_calendar.calendar.startdate IS \'(DC2Type:date_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_calendar.calendar.enddate IS \'(DC2Type:date_immutable)\''); + } +} From b7c5a459f7871c16eee95a303a1be44fbf7a609e Mon Sep 17 00:00:00 2001 From: nobohan Date: Fri, 23 Jul 2021 16:31:36 +0200 Subject: [PATCH 36/59] rdv: change type of date to datetime in calendarRange --- .../Entity/CalendarRange.php | 4 +- .../migrations/Version20210723142842.php | 39 +++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 src/Bundle/ChillCalendarBundle/migrations/Version20210723142842.php diff --git a/src/Bundle/ChillCalendarBundle/Entity/CalendarRange.php b/src/Bundle/ChillCalendarBundle/Entity/CalendarRange.php index 6663d2ff9..1e9280b7d 100644 --- a/src/Bundle/ChillCalendarBundle/Entity/CalendarRange.php +++ b/src/Bundle/ChillCalendarBundle/Entity/CalendarRange.php @@ -25,12 +25,12 @@ class CalendarRange private User $user; /** - * @ORM\Column(type="date_immutable") + * @ORM\Column(type="datetimetz_immutable") */ private \DateTimeImmutable $startDate; /** - * @ORM\Column(type="date_immutable") + * @ORM\Column(type="datetimetz_immutable") */ private \DateTimeImmutable $endDate; diff --git a/src/Bundle/ChillCalendarBundle/migrations/Version20210723142842.php b/src/Bundle/ChillCalendarBundle/migrations/Version20210723142842.php new file mode 100644 index 000000000..5b77338c3 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/migrations/Version20210723142842.php @@ -0,0 +1,39 @@ +addSql('ALTER TABLE chill_calendar.calendar_range ALTER startdate TYPE TIMESTAMP(0) WITH TIME ZONE'); + $this->addSql('ALTER TABLE chill_calendar.calendar_range ALTER startdate DROP DEFAULT'); + $this->addSql('ALTER TABLE chill_calendar.calendar_range ALTER enddate TYPE TIMESTAMP(0) WITH TIME ZONE'); + $this->addSql('ALTER TABLE chill_calendar.calendar_range ALTER enddate DROP DEFAULT'); + $this->addSql('COMMENT ON COLUMN chill_calendar.calendar_range.startDate IS \'(DC2Type:datetimetz_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_calendar.calendar_range.endDate IS \'(DC2Type:datetimetz_immutable)\''); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE chill_calendar.calendar_range ALTER startDate TYPE DATE'); + $this->addSql('ALTER TABLE chill_calendar.calendar_range ALTER startDate DROP DEFAULT'); + $this->addSql('ALTER TABLE chill_calendar.calendar_range ALTER endDate TYPE DATE'); + $this->addSql('ALTER TABLE chill_calendar.calendar_range ALTER endDate DROP DEFAULT'); + $this->addSql('COMMENT ON COLUMN chill_calendar.calendar_range.startdate IS \'(DC2Type:date_immutable)\''); + $this->addSql('COMMENT ON COLUMN chill_calendar.calendar_range.enddate IS \'(DC2Type:date_immutable)\''); + } +} From b106a03534fecd263812a3ed9a661e15e14d551f Mon Sep 17 00:00:00 2001 From: nobohan Date: Fri, 23 Jul 2021 16:42:43 +0200 Subject: [PATCH 37/59] rdv: hook i18n translations into the App.vue --- .../Resources/public/vuejs/Calendar/i18n.js | 2 ++ .../public/vuejs/_components/CalendarRange/js/i18n.js | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/i18n.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/i18n.js index 778072e61..a2d6c62d4 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/i18n.js +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/i18n.js @@ -1,4 +1,5 @@ import { personMessages } from 'ChillPersonAssets/vuejs/_js/i18n' +import { calendarRangeMessages } from '../_components/CalendarRange/js/i18n' const appMessages = { fr: { @@ -14,6 +15,7 @@ const appMessages = { } Object.assign(appMessages.fr, personMessages.fr); +Object.assign(appMessages.fr, calendarRangeMessages.fr); export { appMessages diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarRange/js/i18n.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarRange/js/i18n.js index 5f1dd867a..10aa1d371 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarRange/js/i18n.js +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarRange/js/i18n.js @@ -1,10 +1,10 @@ -const calendarMessages = { +const calendarRangeMessages = { fr: { choose_your_date: 'Sélectionnez vos dates', } }; export { - calendarMessages + calendarRangeMessages }; \ No newline at end of file From 95b50f2b99eef7d9e0ffc82829ab2b6181034e08 Mon Sep 17 00:00:00 2001 From: nobohan Date: Mon, 16 Aug 2021 10:20:01 +0200 Subject: [PATCH 38/59] rdv: add calendar list in menu --- .../Menu/AccompanyingCourseMenuBuilder.php | 47 +++++++++++++++++++ .../Resources/config/services.yml | 6 +++ 2 files changed, 53 insertions(+) create mode 100644 src/Bundle/ChillCalendarBundle/Menu/AccompanyingCourseMenuBuilder.php diff --git a/src/Bundle/ChillCalendarBundle/Menu/AccompanyingCourseMenuBuilder.php b/src/Bundle/ChillCalendarBundle/Menu/AccompanyingCourseMenuBuilder.php new file mode 100644 index 000000000..949dc0560 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Menu/AccompanyingCourseMenuBuilder.php @@ -0,0 +1,47 @@ +translator = $translator; + $this->authorizationHelper = $authorizationHelper; + $this->tokenStorage = $tokenStorage; + } + public static function getMenuIds(): array + { + return ['accompanyingCourse']; + } + + public function buildMenu($menuId, MenuItem $menu, array $parameters) + { + $period = $parameters['accompanyingCourse']; + + if (AccompanyingPeriod::STEP_DRAFT !== $period->getStep()) { + $menu->addChild($this->translator->trans('Calendar list'), [ + 'route' => 'chill_calendar_calendar', + 'routeParameters' => [ + 'accompanying_period_id' => $period->getId(), + ]]) + ->setExtras(['order' => 41]); + } + } +} diff --git a/src/Bundle/ChillCalendarBundle/Resources/config/services.yml b/src/Bundle/ChillCalendarBundle/Resources/config/services.yml index 4810e877b..c41c2ad93 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/config/services.yml +++ b/src/Bundle/ChillCalendarBundle/Resources/config/services.yml @@ -6,3 +6,9 @@ services: resource: '../../Repository/' tags: - { name: 'doctrine.repository_service' } + + Chill\CalendarBundle\Menu\: + autowire: true + autoconfigure: true + resource: '../../Menu/' + tags: ['chill.menu_builder'] From dc3c8a4032fd77b51782bfb1536fa0babb17a11c Mon Sep 17 00:00:00 2001 From: nobohan Date: Mon, 16 Aug 2021 10:57:24 +0200 Subject: [PATCH 39/59] rdv: translations + layout (twig) --- .../Resources/views/Calendar/list.html.twig | 14 ++++++++++---- .../translations/messages.fr.yml | 5 ++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/list.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/list.html.twig index cb45bd2ec..c7ad42343 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/list.html.twig +++ b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/list.html.twig @@ -26,15 +26,21 @@
{% if calendar.startDate %} -

{{ calendar.startDate|format_date('long') }}

+

{{ calendar.startDate|format_datetime('long') }}

{% endif %} {% if calendar.endDate %} -

{{ calendar.endDate|format_date('long') }}

+

{{ calendar.endDate|format_datetime('long') }}

{% endif %} -

{{ calendar.endDate.diff(calendar.startDate)|date("%Y%m%d%h") }}

- + +
+

+ + {{ calendar.endDate.diff(calendar.startDate)|date("%H:%M")}} +

+
+ {% if context == 'user' and calendar.accompanyingPeriod is not empty %}
+
+ + + diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/js/api.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/js/api.js index 839933f29..19780a86e 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/js/api.js +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/js/api.js @@ -12,14 +12,6 @@ const fetchCalendarRanges = () => { }); }; -const getUniqueUserCalendarRanges = () => { //TODO build the array with fetchCalendarRanges - return [ - {userId: 1, username: 'blop'}, - {userId: 2, username: 'blup'} - ]; -} - export { - fetchCalendarRanges, - getUniqueUserCalendarRanges + fetchCalendarRanges }; From e499ebdf8b550eed2a98b02c8787f4ef5835736d Mon Sep 17 00:00:00 2001 From: nobohan Date: Tue, 17 Aug 2021 21:06:32 +0200 Subject: [PATCH 47/59] rdv: add dynamic event sources in fullcalendar (WIP) --- .../Resources/public/vuejs/Calendar/App.vue | 80 ++++++- .../CalendarEvent/CalendarEvent.vue | 213 +++++++++--------- .../CalendarUserSelector.vue | 55 ++++- 3 files changed, 230 insertions(+), 118 deletions(-) diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue index 37caa7b73..a2ca1e5aa 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue @@ -1,20 +1,82 @@ diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarEvent/CalendarEvent.vue b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarEvent/CalendarEvent.vue index 3a59aa28c..93749a598 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarEvent/CalendarEvent.vue +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarEvent/CalendarEvent.vue @@ -18,23 +18,23 @@ export default { components: { FullCalendar }, + props: ['calendarEvents'], data() { return { - calendarRanges: [], + //calendarRanges: [], calendarOptions: { plugins: [ dayGridPlugin, interactionPlugin, timeGridPlugin ], initialView: 'timeGridWeek', - initialEvents: window.startDate !== undefined ? - [ - { - id: 1, - start: window.startDate, - end: window.endDate - } - ] : [], + // initialEvents: window.startDate !== undefined ? + // [ + // { + // id: 1, + // start: window.startDate, + // end: window.endDate + // } + // ] : [], initialDate: window.startDate !== undefined ? window.startDate : new Date(), - //events: this.displayEvents(), - eventSources: this.getEventsSources(), + eventSources: this.calendarEvents, selectable: true, select: this.onDateSelect, eventChange: this.onEventChange, @@ -47,103 +47,108 @@ export default { right: 'dayGridMonth,timeGridWeek,timeGridDay' }, }, - errorMsg: {}, + errorMsg: [], } }, methods: { - getCalendarRanges(userId) { - console.log('get Calendar Ranges'); - return fetchCalendarRanges().then(calendarRanges => new Promise((resolve, reject) => { - console.log(calendarRanges); - this.calendarRanges = calendarRanges.results; - let source = { //TODO transform the results above into a object as following - events: [ - { - title: 'Event1', - start: '2021-07-04T09:30:00' - }, - { - title: 'Event2', - start: '2021-07-05T09:30:00' - } - ], - color: 'red', // an option! - textColor: 'white' // an option! - }; - this.calendarRanges = source; - resolve() - })) - .catch((error) => { - this.errorMsg.push(error.message); - }); + init() { + this.getCalendarRanges() + console.log(window.startDate) }, - getEventsSources() { // soit on appelle cette function plus tard, soit on gère différement l'asynchroniété - let userId = 1; - let arr = [ - this.displayEventSource1(), - this.displayEventSource2(), - - fetchCalendarRanges().then(response => { - console.log(response) - return response - // if (response.ok) { return response.results } - }) - //this.calendarRanges - ]; - console.log(arr); - return arr; - }, - displayEvents() { //TODO WIP - return [ - { - title : 'event1', - start : '2021-07-04T10:30:00' - }, - { - title : 'event2', - start : '2021-07-05', - end : '2021-07-07' - }, - { - title : 'event3', - start : '2021-07-09T12:30:00', - allDay : false // will make the time show - } - ] - //return this.calendarRanges // undefined as not fetched when evaluated - }, - displayEventSource1(){ // TODO replace this with the fetch function depending on the User calendar ranges - return { - events: [ - { - title: 'Event1', - start: '2021-07-04T12:30:00' - }, - { - title: 'Event2', - start: '2021-07-05T12:30:00' - } - ], - color: 'yellow', // an option! - textColor: 'black' // an option! - } - }, - displayEventSource2(){ - return { - events: [ - { - title: 'Event1', - start: '2021-08-04T12:30:00' - }, - { - title: 'Event2', - start: '2021-08-05T12:30:00' - } - ], - color: 'green', // an option! - textColor: 'red' // an option! - } + getCalendarRanges() { + // console.log('getCalendarRanges') + // fetchCalendarRanges().then(calendarRanges => new Promise((resolve, reject) => { + // // let calendarEvents = []; + + // // this.users.loaded.forEach(u => { + // // let arr = calendarRanges.results.filter(i => i.user.id = u.id); + // // console.log(arr) + // // calendarEvents.push({ + // // events: arr, + // // color: u.color + // // }) + // // }) + + // // this.calendarEvents = [ + // // { + // // events: [ + // // { + // // title: 'Event1', + // // start: '2021-08-04T12:30:00' + // // }, + // // { + // // title: 'Event2', + // // start: '2021-08-05T12:30:00' + // // } + // // ], + // // color: 'yellow', // an option! + // // textColor: 'black' // an option! + // // } + // // ] + // // console.log(calendarEvents) + // // this.calendarEvents = calendarEvents; + // resolve() + // })) + // .catch((error) => { + // this.errorMsg.push(error.message); + // }); }, + + // getCalendarRanges(userId) { + // console.log('get Calendar Ranges'); + // return fetchCalendarRanges().then(calendarRanges => new Promise((resolve, reject) => { + // console.log(calendarRanges); + // this.calendarRanges = calendarRanges.results; + // let source = { //TODO transform the results above into a object as following + // events: [ + // { + // title: 'Event1', + // start: '2021-07-04T09:30:00' + // }, + // { + // title: 'Event2', + // start: '2021-07-05T09:30:00' + // } + // ], + // color: 'red', // an option! + // textColor: 'white' // an option! + // }; + // this.calendarRanges = source; + // resolve() + // })) + // .catch((error) => { + // this.errorMsg.push(error.message); + // }); + // }, + // getEventsSources() { // soit on appelle cette function plus tard, soit on gère différement l'asynchroniété + // let arr = [ + // this.displayEventSource1(), + // fetchCalendarRanges().then(response => { + // console.log(response) + // return response + // // if (response.ok) { return response.results } + // }) + // //this.calendarRanges + // ]; + // console.log(arr); + // return arr; + // }, + // displayEventSource1(){ // TODO replace this with the fetch function depending on the User calendar ranges + // return { + // events: [ + // { + // title: 'Event1', + // start: '2021-07-04T12:30:00' + // }, + // { + // title: 'Event2', + // start: '2021-07-05T12:30:00' + // } + // ], + // color: 'yellow', // an option! + // textColor: 'black' // an option! + // } + // }, onDateSelect(payload) { this.$store.dispatch('createEvent', payload); }, @@ -152,7 +157,7 @@ export default { } }, mounted() { - this.getCalendarRanges() + this.init() } } diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue index 839b6dd06..40fc4e2cd 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue @@ -13,7 +13,7 @@ :close-on-select="false" :allow-empty="true" :model-value="value" - @update:model-value="updateUsers" + @update:model-value="selectUsers" :options="options">
@@ -23,9 +23,12 @@ import { fetchCalendarRanges } from './js/api' import VueMultiselect from 'vue-multiselect'; +const COLORS = ['red', 'green', 'yellow', 'blue', 'orange', 'white', 'grey']; + export default { name: 'CalendarUserSelector', components: { VueMultiselect }, + props: ['users', 'updateEventsSource', 'calendarEvents'], data() { return { errorMsg: [], @@ -39,16 +42,57 @@ export default { }, getUniqueUserCalendarRanges() { fetchCalendarRanges().then(calendarRanges => new Promise((resolve, reject) => { + let results = calendarRanges.results; + let users = []; - calendarRanges.results.forEach(i => { + + results.forEach(i => { if (!(users.some(j => i.user.id === j.id))){ users.push({ id: i.user.id, - username: i.user.username + username: i.user.username, + color: COLORS[users.length] //TODO manage case where indice is larger than COLORS; Do something recursive with a max. value }) } }); + + let calendarEvents = []; + users.forEach(u => { + let arr = results.filter(i => i.user.id === u.id).map(i => + ({ + start: i.startDate.datetime, + end: i.endDate.datetime + }) + ); + console.log(arr); + calendarEvents.push({ + events: arr, + color: u.color + }) + }) + + console.log(users) + this.users.loaded = users; this.options = users; + + console.log(calendarEvents) + this.calendarEvents.loaded = calendarEvents; + + // // TO TEST + // this.calendarEvents.loaded = [{events: [ + // { + // title: 'Event1', + // start: '2021-08-04T12:30:00' + // }, + // { + // title: 'Event2', + // start: '2021-08-05T12:30:00' + // } + // ], + // color: 'yellow', // an option! + // textColor: 'black' // an option! + // }]; + resolve() })) .catch((error) => { @@ -58,8 +102,9 @@ export default { transName(value) { return `${value.username}`; }, - updateUsers(value) { - console.log(value) + selectUsers(value) { + this.users.selected = value; + this.updateEventsSource(); } }, mounted() { From e6deb6bc7a2609d5f2c0554e5d0bd6f195381959 Mon Sep 17 00:00:00 2001 From: nobohan Date: Tue, 17 Aug 2021 21:57:43 +0200 Subject: [PATCH 48/59] rdv: fullcalendar: update events source dynamically --- .../Resources/public/vuejs/Calendar/App.vue | 112 +++++++----- .../CalendarEvent/CalendarEvent.vue | 163 ------------------ .../vuejs/_components/CalendarEvent/js/api.js | 17 -- .../_components/CalendarEvent/js/i18n.js | 10 -- 4 files changed, 73 insertions(+), 229 deletions(-) delete mode 100644 src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarEvent/CalendarEvent.vue delete mode 100644 src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarEvent/js/api.js delete mode 100644 src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarEvent/js/i18n.js diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue index a2ca1e5aa..dec188e43 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue @@ -4,24 +4,30 @@ v-bind:users="users" v-bind:calendarEvents="calendarEvents" v-bind:updateEventsSource="updateEventsSource"> - - - + +

{{ $t('choose_your_date') }}

+ + + diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarEvent/CalendarEvent.vue b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarEvent/CalendarEvent.vue deleted file mode 100644 index 93749a598..000000000 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarEvent/CalendarEvent.vue +++ /dev/null @@ -1,163 +0,0 @@ - - diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarEvent/js/api.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarEvent/js/api.js deleted file mode 100644 index 19780a86e..000000000 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarEvent/js/api.js +++ /dev/null @@ -1,17 +0,0 @@ -/* -* Endpoint chill_api_single_calendar_range -* method GET, get Calendar ranges -* @returns {Promise} a promise containing all Calendar ranges objects -*/ -const fetchCalendarRanges = () => { - const url = `/api/1.0/calendar/calendar-range.json?item_per_page=1000`; - return fetch(url) - .then(response => { - if (response.ok) { return response.json(); } - throw Error('Error with request resource response'); - }); -}; - -export { - fetchCalendarRanges -}; diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarEvent/js/i18n.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarEvent/js/i18n.js deleted file mode 100644 index ee95e04b9..000000000 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarEvent/js/i18n.js +++ /dev/null @@ -1,10 +0,0 @@ -const calendarEventMessages = { - fr: { - choose_your_date: 'Sélectionnez vos dates', - } - }; - - export { - calendarEventMessages - }; - \ No newline at end of file From b40c25595a67e15627d4625bbec9178fb9b72900 Mon Sep 17 00:00:00 2001 From: nobohan Date: Wed, 18 Aug 2021 10:16:32 +0200 Subject: [PATCH 49/59] rdv: fullcalendar: select and unselect user calendars --- .../Resources/public/vuejs/Calendar/App.vue | 58 +++++++------------ .../CalendarUserSelector.vue | 34 +++++------ 2 files changed, 35 insertions(+), 57 deletions(-) diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue index dec188e43..504315e99 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue @@ -22,6 +22,15 @@ import dayGridPlugin from '@fullcalendar/daygrid' import interactionPlugin from '@fullcalendar/interaction' import timeGridPlugin from '@fullcalendar/timegrid' +const currentEvent = { + events: [{ + title: 'my_event', + start: window.startDate, + end: window.endDate + }], + id: -1 +}; + export default { name: "App", components: { @@ -38,39 +47,20 @@ export default { }, calendarEvents: { loaded: [], - selected: [] + selected: [], + userEvents: [], //TODO load user calendar events + current: currentEvent }, calendarOptions: { plugins: [ dayGridPlugin, interactionPlugin, timeGridPlugin ], initialView: 'timeGridWeek', - initialEvents: window.startDate !== undefined ? - [ - { - id: 1, - start: window.startDate, - end: window.endDate - } - ] : [], initialDate: window.startDate !== undefined ? window.startDate : new Date(), - // eventSources: [{events: [ - // { - // title: 'Event1', - // start: '2021-08-04T12:30:00' - // }, - // { - // title: 'Event2', - // start: '2021-08-05T12:30:00' - // } - // ], - // color: 'yellow', // an option! - // textColor: 'black' // an option! - // }],//this work at initialisation, initialize with initialEvents content? + eventSources: window.startDate !== undefined ? [currentEvent] : [], selectable: true, select: this.onDateSelect, eventChange: this.onEventChange, selectMirror: true, editable: true, - lazyFetching: false, // To fetch at maximum headerToolbar: { left: 'prev,next today', center: 'title', @@ -82,25 +72,17 @@ export default { methods: { init() { console.log(window.startDate) - let calendar = this.$refs.fullCalendar.getApi() - //calendar.next() - console.log(calendar) + // let calendar = this.$refs.fullCalendar.getApi() + // console.log(calendar) }, updateEventsSource() { console.log('updateEventsSource') - - console.log(this.calendarEvents.loaded); - this.calendarEvents.selected = this.calendarEvents.loaded; //TODO filter loaded events on selected users - - // this works!!! + console.log(this.calendarEvents.selected) + this.calendarOptions.eventSources = this.calendarEvents.selected; - - // let calendar = this.$refs.fullCalendar.getApi(); - // console.log(calendar); - // console.log(calendar.getEventSources()) - // calendar.addEventSource(this.calendarEvents.selected); - - // console.log(calendar.getEventSources()) + if (window.startDate !== undefined) { + this.calendarEvents.selected.push(currentEvent); + } }, onDateSelect(payload) { this.$store.dispatch('createEvent', payload); diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue index 40fc4e2cd..fbb5201c3 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue @@ -13,7 +13,8 @@ :close-on-select="false" :allow-empty="true" :model-value="value" - @update:model-value="selectUsers" + @select="selectUsers" + @remove="unSelectUsers" :options="options">
@@ -64,10 +65,10 @@ export default { end: i.endDate.datetime }) ); - console.log(arr); calendarEvents.push({ events: arr, - color: u.color + color: u.color, + id: u.id }) }) @@ -78,21 +79,6 @@ export default { console.log(calendarEvents) this.calendarEvents.loaded = calendarEvents; - // // TO TEST - // this.calendarEvents.loaded = [{events: [ - // { - // title: 'Event1', - // start: '2021-08-04T12:30:00' - // }, - // { - // title: 'Event2', - // start: '2021-08-05T12:30:00' - // } - // ], - // color: 'yellow', // an option! - // textColor: 'black' // an option! - // }]; - resolve() })) .catch((error) => { @@ -102,8 +88,18 @@ export default { transName(value) { return `${value.username}`; }, + selectEvents() { + let selectedUsersId = this.users.selected.map(a => a.id); + this.calendarEvents.selected = this.calendarEvents.loaded.filter(a => selectedUsersId.includes(a.id)); + }, selectUsers(value) { - this.users.selected = value; + this.users.selected.push(value); + this.selectEvents(); + this.updateEventsSource(); + }, + unSelectUsers(value) { + this.users.selected = this.users.selected.filter(a => a.id != value.id); + this.selectEvents(); this.updateEventsSource(); } }, From ca9738b55a9d309a51829ade3210fa2f39ef45b8 Mon Sep 17 00:00:00 2001 From: nobohan Date: Wed, 18 Aug 2021 10:48:41 +0200 Subject: [PATCH 50/59] rdv: fullcalendar: add current user by default --- .../CalendarUserSelector/CalendarUserSelector.vue | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue index fbb5201c3..7e76dfb6b 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue @@ -23,6 +23,7 @@ import { fetchCalendarRanges } from './js/api' import VueMultiselect from 'vue-multiselect'; +import { whoami } from 'ChillPersonAssets/vuejs/AccompanyingCourse/api'; const COLORS = ['red', 'green', 'yellow', 'blue', 'orange', 'white', 'grey']; @@ -78,6 +79,13 @@ export default { console.log(calendarEvents) this.calendarEvents.loaded = calendarEvents; + whoami().then(me => new Promise((resolve, reject) => { + let currentUser = users.find(u => u.id === me.id); + this.value = currentUser; + this.selectUsers(currentUser); + resolve(); + })); + resolve() })) From a54434a677f90af6695651df76d9923393353ca2 Mon Sep 17 00:00:00 2001 From: nobohan Date: Wed, 18 Aug 2021 12:59:05 +0200 Subject: [PATCH 51/59] rdv: add fr locale to fullcalendar + colorise users calendars --- .../Resources/public/vuejs/Calendar/App.vue | 5 ++- .../Resources/public/vuejs/Calendar/i18n.js | 3 +- .../CalendarUserSelector.vue | 42 ++++++++++++++++--- 3 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue index 504315e99..2aa307b64 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue @@ -17,10 +17,12 @@ import ConcernedGroups from 'ChillActivityAssets/vuejs/Activity/components/ConcernedGroups.vue'; import CalendarUserSelector from '../_components/CalendarUserSelector/CalendarUserSelector.vue'; import '@fullcalendar/core/vdom' // solves problem with Vite +import frLocale from '@fullcalendar/core/locales/fr'; import FullCalendar from '@fullcalendar/vue3' import dayGridPlugin from '@fullcalendar/daygrid' import interactionPlugin from '@fullcalendar/interaction' import timeGridPlugin from '@fullcalendar/timegrid' +import listPlugin from '@fullcalendar/list'; const currentEvent = { events: [{ @@ -52,7 +54,8 @@ export default { current: currentEvent }, calendarOptions: { - plugins: [ dayGridPlugin, interactionPlugin, timeGridPlugin ], + locale: frLocale, + plugins: [ dayGridPlugin, interactionPlugin, timeGridPlugin, listPlugin ], initialView: 'timeGridWeek', initialDate: window.startDate !== undefined ? window.startDate : new Date(), eventSources: window.startDate !== undefined ? [currentEvent] : [], diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/i18n.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/i18n.js index 8d40aba13..c086fed07 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/i18n.js +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/i18n.js @@ -1,9 +1,9 @@ import { personMessages } from 'ChillPersonAssets/vuejs/_js/i18n' -import { calendarEventMessages } from '../_components/CalendarEvent/js/i18n' import { calendarUserSelectorMessages } from '../_components/CalendarUserSelector/js/i18n'; const appMessages = { fr: { + choose_your_date: "Sélectionnez votre plage", activity: { add_persons: "Ajouter des personnes concernées", bloc_persons: "Usagers", @@ -16,7 +16,6 @@ const appMessages = { } Object.assign(appMessages.fr, personMessages.fr); -Object.assign(appMessages.fr, calendarEventMessages.fr); Object.assign(appMessages.fr, calendarUserSelectorMessages.fr); export { diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue index 7e76dfb6b..520104b79 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue @@ -15,6 +15,7 @@ :model-value="value" @select="selectUsers" @remove="unSelectUsers" + @close="coloriseSelectedValues" :options="options">
@@ -25,7 +26,20 @@ import { fetchCalendarRanges } from './js/api' import VueMultiselect from 'vue-multiselect'; import { whoami } from 'ChillPersonAssets/vuejs/AccompanyingCourse/api'; -const COLORS = ['red', 'green', 'yellow', 'blue', 'orange', 'white', 'grey']; +const COLORS = [ /* from https://colorbrewer2.org/#type=qualitative&scheme=Set3&n=12 */ + '#8dd3c7', + '#ffffb3', + '#bebada', + '#fb8072', + '#80b1d3', + '#fdb462', + '#b3de69', + '#fccde5', + '#d9d9d9', + '#bc80bd', + '#ccebc5', + '#ffed6f' +]; export default { name: 'CalendarUserSelector', @@ -50,10 +64,12 @@ export default { results.forEach(i => { if (!(users.some(j => i.user.id === j.id))){ + let ratio = Math.floor(users.length / COLORS.length); + let colorIndex = users.length - ratio * COLORS.length; users.push({ id: i.user.id, username: i.user.username, - color: COLORS[users.length] //TODO manage case where indice is larger than COLORS; Do something recursive with a max. value + color: COLORS[colorIndex] }) } }); @@ -73,20 +89,18 @@ export default { }) }) - console.log(users) this.users.loaded = users; this.options = users; - console.log(calendarEvents) this.calendarEvents.loaded = calendarEvents; whoami().then(me => new Promise((resolve, reject) => { let currentUser = users.find(u => u.id === me.id); this.value = currentUser; this.selectUsers(currentUser); + resolve(); })); - resolve() })) .catch((error) => { @@ -96,12 +110,30 @@ export default { transName(value) { return `${value.username}`; }, + coloriseSelectedValues() { //TODO cette function doit être exécutée au bon moment, après sélection (normalement avec @input) + let tags = document.querySelectorAll('div.multiselect__tags-wrap')[0]; + + if (tags.hasChildNodes()) { + let children = tags.childNodes; + for (let i = 0; i < children.length; i++) { + let child = children[i]; + if (child.nodeType === Node.ELEMENT_NODE) { + this.users.selected.forEach(u => { + if (child.firstChild.innerText == u.username) { + child.style.background = u.color; + } + }) + } + } + } + }, selectEvents() { let selectedUsersId = this.users.selected.map(a => a.id); this.calendarEvents.selected = this.calendarEvents.loaded.filter(a => selectedUsersId.includes(a.id)); }, selectUsers(value) { this.users.selected.push(value); + this.coloriseSelectedValues(); this.selectEvents(); this.updateEventsSource(); }, From 07eb5c797aa3a158d1ca99f581e2bf8c6c8aafa3 Mon Sep 17 00:00:00 2001 From: nobohan Date: Wed, 18 Aug 2021 15:12:24 +0200 Subject: [PATCH 52/59] rdv: fullcalendar: manage event clicking --- .../Resources/public/vuejs/Calendar/App.vue | 17 ++++++++++- .../Resources/public/vuejs/Calendar/store.js | 1 - .../CalendarUserSelector.vue | 28 ++++++++----------- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue index 2aa307b64..d741ac924 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue @@ -62,12 +62,15 @@ export default { selectable: true, select: this.onDateSelect, eventChange: this.onEventChange, + eventClick: this.onEventClick, + eventMouseEnter: this.onEventMouseEnter, + eventMouseLeave: this.onEventMouseLeave, selectMirror: true, editable: true, headerToolbar: { left: 'prev,next today', center: 'title', - right: 'dayGridMonth,timeGridWeek,timeGridDay' + right: 'dayGridMonth,timeGridWeek,timeGridDay,listMonth,listWeek,listDay' }, } } @@ -92,6 +95,17 @@ export default { }, onEventChange(payload) { this.$store.dispatch('updateEvent', payload); + }, + onEventClick(payload) { + payload.event.setProp('backgroundColor','#3788d8'); + payload.event.setProp('textColor','#ffffff'); + this.$store.dispatch('updateEvent', payload); + }, + onEventMouseEnter(payload) { + payload.event.setProp('borderColor','#444444'); + }, + onEventMouseLeave(payload) { + payload.event.setProp('borderColor','#ffffff'); } }, mounted() { @@ -99,3 +113,4 @@ export default { } } + diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js index 79c3db5d0..8fae5eb00 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js @@ -118,7 +118,6 @@ const store = createStore({ updateEvent({ commit }, payload) { console.log('### action updateEvent', payload); let startDateInput = document.getElementById("chill_calendarbundle_calendar_startDate"); - console.log(payload.event) startDateInput.value = payload.event.start.toISOString(); let endDateInput = document.getElementById("chill_calendarbundle_calendar_endDate"); endDateInput.value = payload.event.end.toISOString(); diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue index 520104b79..48bb02802 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue @@ -79,12 +79,14 @@ export default { let arr = results.filter(i => i.user.id === u.id).map(i => ({ start: i.startDate.datetime, - end: i.endDate.datetime + end: i.endDate.datetime, + //display: 'background' // can be an option for the disponibility }) ); calendarEvents.push({ events: arr, color: u.color, + textColor: '#444444', id: u.id }) }) @@ -119,10 +121,14 @@ export default { let child = children[i]; if (child.nodeType === Node.ELEMENT_NODE) { this.users.selected.forEach(u => { - if (child.firstChild.innerText == u.username) { - child.style.background = u.color; + if (child.hasChildNodes()) { + if (child.firstChild.innerText == u.username) { + child.style.background = u.color; + child.firstChild.style.color = '#444444'; + } + } } - }) + ) } } } @@ -150,16 +156,4 @@ export default { - + From a70d5cc263c0b226f5cbad641ad259a0c746faa2 Mon Sep 17 00:00:00 2001 From: nobohan Date: Wed, 18 Aug 2021 15:54:35 +0200 Subject: [PATCH 53/59] rdv: fullcalendar: save calendarRange id as an extended prop in the calendar entity --- .../ChillCalendarBundle/Form/CalendarType.php | 19 +++++++++++++++++++ .../Resources/public/vuejs/Calendar/App.vue | 11 +++++------ .../Resources/public/vuejs/Calendar/store.js | 6 ++++-- .../CalendarUserSelector.vue | 3 ++- .../Resources/views/Calendar/edit.html.twig | 4 ++++ .../Resources/views/Calendar/new.html.twig | 4 ++++ 6 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/Bundle/ChillCalendarBundle/Form/CalendarType.php b/src/Bundle/ChillCalendarBundle/Form/CalendarType.php index 9ff29a52c..30b9651a7 100644 --- a/src/Bundle/ChillCalendarBundle/Form/CalendarType.php +++ b/src/Bundle/ChillCalendarBundle/Form/CalendarType.php @@ -15,6 +15,7 @@ use Symfony\Component\Form\Extension\Core\Type\HiddenType; use Chill\MainBundle\Form\Type\CommentType; use Chill\CalendarBundle\Entity\Calendar; +use Chill\CalendarBundle\Entity\CalendarRange; use Chill\CalendarBundle\Entity\CancelReason; use Chill\CalendarBundle\Entity\Invite; use Chill\MainBundle\Entity\User; @@ -145,6 +146,24 @@ class CalendarType extends AbstractType )) ; + $builder->add('calendarRange', HiddenType::class); + $builder->get('calendarRange') + ->addModelTransformer(new CallbackTransformer( + function (?CalendarRange $calendarRange): int { + if (NULL !== $calendarRange) { + $res = $calendarRange->getId(); + } else { + $res = -1; + } + return $res; + }, + function (?string $calendarRangeId): CalendarRange { + return $this->om->getRepository(CalendarRange::class)->findOneBy(['id' => (int) $calendarRangeId]); + } + )) + ; + + // $builder->add('invites', HiddenType::class); // $builder->get('invites') // ->addModelTransformer(new CallbackTransformer( diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue index d741ac924..3a7db6dc4 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue @@ -63,8 +63,8 @@ export default { select: this.onDateSelect, eventChange: this.onEventChange, eventClick: this.onEventClick, - eventMouseEnter: this.onEventMouseEnter, - eventMouseLeave: this.onEventMouseLeave, + // eventMouseEnter: this.onEventMouseEnter, + // eventMouseLeave: this.onEventMouseLeave, selectMirror: true, editable: true, headerToolbar: { @@ -82,9 +82,6 @@ export default { // console.log(calendar) }, updateEventsSource() { - console.log('updateEventsSource') - console.log(this.calendarEvents.selected) - this.calendarOptions.eventSources = this.calendarEvents.selected; if (window.startDate !== undefined) { this.calendarEvents.selected.push(currentEvent); @@ -94,12 +91,14 @@ export default { this.$store.dispatch('createEvent', payload); }, onEventChange(payload) { + console.log(payload.event.extendedProps); + console.log(this.calendarOptions.eventSources) this.$store.dispatch('updateEvent', payload); }, onEventClick(payload) { payload.event.setProp('backgroundColor','#3788d8'); payload.event.setProp('textColor','#ffffff'); - this.$store.dispatch('updateEvent', payload); + //this.$store.dispatch('updateEvent', payload); }, onEventMouseEnter(payload) { payload.event.setProp('borderColor','#444444'); diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js index 8fae5eb00..20ed3118c 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js @@ -29,7 +29,7 @@ const store = createStore({ strict: debug, state: { activity: mapEntity(window.entity), - events: [] + currentEvent: null }, mutations: { @@ -65,7 +65,7 @@ const store = createStore({ // Calendar setEvents(state, payload) { console.log(payload) - state.events.push( {start: payload.start, end: payload.end}) + state.currentEvent = {start: payload.start, end: payload.end} } }, actions: { @@ -121,6 +121,8 @@ const store = createStore({ startDateInput.value = payload.event.start.toISOString(); let endDateInput = document.getElementById("chill_calendarbundle_calendar_endDate"); endDateInput.value = payload.event.end.toISOString(); + let calendarRangeInput = document.getElementById("chill_calendarbundle_calendar_calendarRange"); + calendarRangeInput.value = payload.event.extendedProps.calendarRangeId; commit('setEvents', payload); }, diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue index 48bb02802..95706fd8f 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue @@ -80,6 +80,7 @@ export default { ({ start: i.startDate.datetime, end: i.endDate.datetime, + calendarRangeId: i.id //display: 'background' // can be an option for the disponibility }) ); @@ -93,7 +94,7 @@ export default { this.users.loaded = users; this.options = users; - + console.log(calendarEvents) this.calendarEvents.loaded = calendarEvents; whoami().then(me => new Promise((resolve, reject) => { let currentUser = users.find(u => u.id === me.id); diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/edit.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/edit.html.twig index ddb34b345..784d3686d 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/edit.html.twig +++ b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/edit.html.twig @@ -34,6 +34,10 @@ {{ form_row(form.endDate) }} {% endif %} +{%- if form.calendarRange is defined -%} + {{ form_row(form.calendarRange) }} +{% endif %} + .. location {%- if form.cancelReason is defined -%} diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/new.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/new.html.twig index 104b7caf2..501f2ebe1 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/new.html.twig +++ b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/new.html.twig @@ -34,6 +34,10 @@ {{ form_row(form.endDate) }} {% endif %} +{%- if form.calendarRange is defined -%} + {{ form_row(form.calendarRange) }} +{% endif %} + .. location {%- if form.cancelReason is defined -%} From dbf72774c24f6ca7f26c5206d59b68cda091ce12 Mon Sep 17 00:00:00 2001 From: nobohan Date: Wed, 18 Aug 2021 16:51:16 +0200 Subject: [PATCH 54/59] rdv: add main user in fullcalendar form --- .../ChillCalendarBundle/Form/CalendarType.php | 37 +++++++++++++------ .../Resources/public/vuejs/Calendar/App.vue | 9 ++++- .../Resources/public/vuejs/Calendar/store.js | 8 +++- .../CalendarUserSelector.vue | 4 ++ .../Calendar/editAccompanyingCourse.html.twig | 1 + 5 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/Bundle/ChillCalendarBundle/Form/CalendarType.php b/src/Bundle/ChillCalendarBundle/Form/CalendarType.php index 30b9651a7..c2f3ea6ba 100644 --- a/src/Bundle/ChillCalendarBundle/Form/CalendarType.php +++ b/src/Bundle/ChillCalendarBundle/Form/CalendarType.php @@ -45,14 +45,6 @@ class CalendarType extends AbstractType public function buildForm(FormBuilderInterface $builder, array $options) { $builder - ->add('mainUser', EntityType::class, [ - 'required' => true, - 'class' => User::class, - 'choice_label' => function (User $entity) { - return $entity->getUsernameCanonical(); - }, - // TODO 'empty_data' => - ]) ->add('comment', CommentType::class, [ 'required' => false ]) @@ -73,6 +65,24 @@ class CalendarType extends AbstractType ]) ; + + $builder->add('mainUser', HiddenType::class); + $builder->get('mainUser') + ->addModelTransformer(new CallbackTransformer( + function (?User $user): int { + if (NULL !== $user) { + $res = $user->getId(); + } else { + $res = -1; //TODO cannot be null in any ways... + } + return $res; + }, + function (?int $userId): User { + return $this->om->getRepository(user::class)->findOneBy(['id' => (int) $userId]); + } + )) + ; + $builder->add('startDate', HiddenType::class); $builder->get('startDate') ->addModelTransformer(new CallbackTransformer( @@ -149,7 +159,7 @@ class CalendarType extends AbstractType $builder->add('calendarRange', HiddenType::class); $builder->get('calendarRange') ->addModelTransformer(new CallbackTransformer( - function (?CalendarRange $calendarRange): int { + function (?CalendarRange $calendarRange): ?int { if (NULL !== $calendarRange) { $res = $calendarRange->getId(); } else { @@ -157,8 +167,13 @@ class CalendarType extends AbstractType } return $res; }, - function (?string $calendarRangeId): CalendarRange { - return $this->om->getRepository(CalendarRange::class)->findOneBy(['id' => (int) $calendarRangeId]); + function (?string $calendarRangeId): ?CalendarRange { + if (NULL !== $calendarRangeId) { + $res = $this->om->getRepository(CalendarRange::class)->findOneBy(['id' => (int) $calendarRangeId]); + } else { + $res = NULL; + } + return $res; } )) ; diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue index 3a7db6dc4..65c77c937 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue @@ -30,7 +30,7 @@ const currentEvent = { start: window.startDate, end: window.endDate }], - id: -1 + id: window.mainUser }; export default { @@ -45,7 +45,8 @@ export default { errorMsg: [], users: { loaded: [], - selected: [] + selected: [], + logged: null }, calendarEvents: { loaded: [], @@ -88,10 +89,14 @@ export default { } }, onDateSelect(payload) { + Object.assign(payload, {users: this.users}); this.$store.dispatch('createEvent', payload); }, onEventChange(payload) { + console.log(payload.event); console.log(payload.event.extendedProps); + console.log(payload.event.source); + console.log(payload.event.source.id); console.log(this.calendarOptions.eventSources) this.$store.dispatch('updateEvent', payload); }, diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js index 20ed3118c..ba4329ff4 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js @@ -113,6 +113,9 @@ const store = createStore({ startDateInput.value = payload.startStr; let endDateInput = document.getElementById("chill_calendarbundle_calendar_endDate"); endDateInput.value = payload.endStr; + //TODO specify the mainUserInput value if not from a source + let mainUserInput = document.getElementById("chill_calendarbundle_calendar_mainUser"); + mainUserInput.value = payload.users.logged.id; commit('setEvents', payload); }, updateEvent({ commit }, payload) { @@ -122,7 +125,10 @@ const store = createStore({ let endDateInput = document.getElementById("chill_calendarbundle_calendar_endDate"); endDateInput.value = payload.event.end.toISOString(); let calendarRangeInput = document.getElementById("chill_calendarbundle_calendar_calendarRange"); - calendarRangeInput.value = payload.event.extendedProps.calendarRangeId; + calendarRangeInput.value = Number(payload.event.extendedProps.calendarRangeId); + let mainUserInput = document.getElementById("chill_calendarbundle_calendar_mainUser"); + mainUserInput.value = Number(payload.event.source.id); + //TODO check if working when reiszing an event commit('setEvents', payload); }, diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue index 95706fd8f..a22d0103f 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue @@ -94,9 +94,13 @@ export default { this.users.loaded = users; this.options = users; + + console.log(users) console.log(calendarEvents) + this.calendarEvents.loaded = calendarEvents; whoami().then(me => new Promise((resolve, reject) => { + this.users.logged = me; let currentUser = users.find(u => u.id === me.id); this.value = currentUser; this.selectUsers(currentUser); diff --git a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/editAccompanyingCourse.html.twig b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/editAccompanyingCourse.html.twig index 17e15df66..d0295d0e2 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/editAccompanyingCourse.html.twig +++ b/src/Bundle/ChillCalendarBundle/Resources/views/Calendar/editAccompanyingCourse.html.twig @@ -27,6 +27,7 @@ window.entity = {{ entity_json|json_encode|raw }}; window.startDate = {{ entity.startDate|date('Y-m-d H:i:s')|json_encode|raw }}; window.endDate = {{ entity.endDate|date('Y-m-d H:i:s')|json_encode|raw }}; + window.mainUser = {{ entity.mainUser.id }}; {{ encore_entry_script_tags('vue_calendar') }} {% endblock %} From 7c4f976230dbc9a059002c429c0fc59190b118bb Mon Sep 17 00:00:00 2001 From: nobohan Date: Wed, 18 Aug 2021 23:16:52 +0200 Subject: [PATCH 55/59] rdv: add user calendar endpoint + add this calendar in the calendar --- .../Controller/CalendarAPIController.php | 22 +++++++++++++ .../ChillCalendarExtension.php | 21 +++++++++++++ .../ChillCalendarBundle/Entity/Calendar.php | 5 ++- .../Resources/public/vuejs/Calendar/App.vue | 14 +++++---- .../Resources/public/vuejs/Calendar/store.js | 2 -- .../CalendarUserSelector.vue | 31 ++++++++++++++++--- .../CalendarUserSelector/js/api.js | 19 ++++++++++-- .../ChillTaskBundle/Menu/UserMenuBuilder.php | 14 ++++----- 8 files changed, 105 insertions(+), 23 deletions(-) create mode 100644 src/Bundle/ChillCalendarBundle/Controller/CalendarAPIController.php diff --git a/src/Bundle/ChillCalendarBundle/Controller/CalendarAPIController.php b/src/Bundle/ChillCalendarBundle/Controller/CalendarAPIController.php new file mode 100644 index 000000000..d6e3586b2 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Controller/CalendarAPIController.php @@ -0,0 +1,22 @@ +query->has('main_user')) { + + $qb->where('e.mainUser = :main_user') + ->setParameter('main_user', $request->query->get('main_user')); + + } + } + +} diff --git a/src/Bundle/ChillCalendarBundle/DependencyInjection/ChillCalendarExtension.php b/src/Bundle/ChillCalendarBundle/DependencyInjection/ChillCalendarExtension.php index 8b71b26f0..4b6a0cadf 100644 --- a/src/Bundle/ChillCalendarBundle/DependencyInjection/ChillCalendarExtension.php +++ b/src/Bundle/ChillCalendarBundle/DependencyInjection/ChillCalendarExtension.php @@ -75,6 +75,27 @@ class ChillCalendarExtension extends Extension implements PrependExtensionInterf ] ], ] + ], + [ + 'controller' => \Chill\CalendarBundle\Controller\CalendarAPIController::class, + 'class' => \Chill\CalendarBundle\Entity\Calendar::class, + 'name' => 'calendar', + 'base_path' => '/api/1.0/calendar/calendar', + 'base_role' => 'ROLE_USER', + 'actions' => [ + '_index' => [ + 'methods' => [ + Request::METHOD_GET => true, + Request::METHOD_HEAD => true + ], + ], + '_entity' => [ + 'methods' => [ + Request::METHOD_GET => true, + Request::METHOD_HEAD => true + ] + ], + ] ] ] ]); diff --git a/src/Bundle/ChillCalendarBundle/Entity/Calendar.php b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php index 3ee5bcc54..06a97fd7f 100644 --- a/src/Bundle/ChillCalendarBundle/Entity/Calendar.php +++ b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php @@ -41,17 +41,18 @@ class Calendar /** * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User") + * @Groups({"read"}) */ private User $user; /** * @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod") - * @Groups({"read"}) */ private AccompanyingPeriod $accompanyingPeriod; /** * @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User") + * @Groups({"read"}) */ private ?User $mainUser; @@ -92,11 +93,13 @@ class Calendar /** * @ORM\Column(type="datetimetz_immutable") + * @Groups({"read"}) */ private \DateTimeImmutable $startDate; /** * @ORM\Column(type="datetimetz_immutable") + * @Groups({"read"}) */ private \DateTimeImmutable $endDate; diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue index 65c77c937..7f0082a72 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/App.vue @@ -51,7 +51,7 @@ export default { calendarEvents: { loaded: [], selected: [], - userEvents: [], //TODO load user calendar events + user: [], //TODO load user calendar events current: currentEvent }, calendarOptions: { @@ -81,22 +81,24 @@ export default { console.log(window.startDate) // let calendar = this.$refs.fullCalendar.getApi() // console.log(calendar) + this.calendarEvents.selected.push(this.calendarEvents.user); + this.calendarOptions.eventSources = this.calendarEvents.selected; + console.log(this.calendarOptions.eventSources) + }, updateEventsSource() { - this.calendarOptions.eventSources = this.calendarEvents.selected; if (window.startDate !== undefined) { this.calendarEvents.selected.push(currentEvent); } + this.calendarEvents.selected.push(this.calendarEvents.user); + this.calendarOptions.eventSources = this.calendarEvents.selected; + console.log(this.calendarOptions.eventSources) }, onDateSelect(payload) { Object.assign(payload, {users: this.users}); this.$store.dispatch('createEvent', payload); }, onEventChange(payload) { - console.log(payload.event); - console.log(payload.event.extendedProps); - console.log(payload.event.source); - console.log(payload.event.source.id); console.log(this.calendarOptions.eventSources) this.$store.dispatch('updateEvent', payload); }, diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js index ba4329ff4..03d0548dc 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/Calendar/store.js @@ -113,7 +113,6 @@ const store = createStore({ startDateInput.value = payload.startStr; let endDateInput = document.getElementById("chill_calendarbundle_calendar_endDate"); endDateInput.value = payload.endStr; - //TODO specify the mainUserInput value if not from a source let mainUserInput = document.getElementById("chill_calendarbundle_calendar_mainUser"); mainUserInput.value = payload.users.logged.id; commit('setEvents', payload); @@ -128,7 +127,6 @@ const store = createStore({ calendarRangeInput.value = Number(payload.event.extendedProps.calendarRangeId); let mainUserInput = document.getElementById("chill_calendarbundle_calendar_mainUser"); mainUserInput.value = Number(payload.event.source.id); - //TODO check if working when reiszing an event commit('setEvents', payload); }, diff --git a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue index a22d0103f..064e550a9 100644 --- a/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue +++ b/src/Bundle/ChillCalendarBundle/Resources/public/vuejs/_components/CalendarUserSelector/CalendarUserSelector.vue @@ -22,7 +22,7 @@