diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml new file mode 100644 index 0000000..18697c2 --- /dev/null +++ b/.github/workflows/changelog.yml @@ -0,0 +1,17 @@ +name: 'Generate Auto Changelog' +on: + push: + branches: + - master +jobs: + master: + name: 'build' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + with: + fetch-depth: 0 + - name: Generate Auto Changelog + uses: Evarisk/action-auto-changelog@master + with: + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..538ba41 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +node_modules +npm-debug.log +.idea +vendor +.editorconfig +.gitattributes diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..94a0453 --- /dev/null +++ b/COPYING @@ -0,0 +1,621 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is 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. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + 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. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + 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 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. Use with the GNU Affero General Public License. + + 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 Affero 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 special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 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 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 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 diff --git a/ChangeLog.md b/ChangeLog.md new file mode 100644 index 0000000..072b6fa --- /dev/null +++ b/ChangeLog.md @@ -0,0 +1,5 @@ +# CHANGELOG DOLISIRH FOR [DOLIBARR ERP CRM](https://www.dolibarr.org) + +## 1.0 + +Initial version diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f288702 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is 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. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + 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. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + 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 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. Use with the GNU Affero General Public License. + + 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 Affero 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 special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 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 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 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 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + 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 GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.md b/README.md new file mode 100644 index 0000000..11166f7 --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +# DOLISIRH POUR [DOLIBARR ERP CRM](https://www.dolibarr.org) + +## Informations + +Version du module: 1.3.0 + +Dernière mise à jour: 18/08/2022 + +Prérequis: +* Dolibarr min version 14.0.0 +* Dolibarr min version 15.0.3 + +Thème: Eldy Menu + +Editeur/Licence: [Eoxia](https://www.eoxia.com) / GPL-v3 + +Assitance: [Forum www.dolibarr.fr](https://www.dolibarr.fr) / Par mail à contact@eoxia.com + +Demo: [Demo DoliSIRH](https://www.dolisirh.projetm.com) - ID: demo - Password: demo + +Documentation: [Wiki DoliSIRH](https://wiki.dolibarr.org/index.php/Module_DoliSIRH) + +## Fonctionnalités + +- Module ajoutant la possibilité de simplifier la création de tâche liée à un projet à partir d'une facture. +- Module ajoutant la possibilité de simplifier la création d'un temps consommé lié à une tâche à partir d'un ticket. + +## Installation + +# Méthode 1 : + +- Depuis le menu "Déployer/Installer un module externe" de Dolibarr : +- Glisser l'archive ZIP 'module_dolisirh-1.2.0' et cliquer sur "SEND" +- Activer le module dans la liste des Modules/Applications installés + +# Méthode 2 : + +- Dans le dossier "dolibarr/htdocs/custom" copier la ligne suivante : +``` +git clone https://github.com/Eoxia/dolisirh.git +``` diff --git a/admin/about.php b/admin/about.php new file mode 100644 index 0000000..a287422 --- /dev/null +++ b/admin/about.php @@ -0,0 +1,80 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file admin/about.php + * \ingroup dolisirh + * \brief About page of module DoliSIRH. + */ + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +// Try main.inc.php using relative path +if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; +if (!$res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; +if (!$res) die("Include of main fails"); + +// Libraries +require_once '../lib/dolisirh.lib.php'; +require_once '../core/modules/modDolisirh.class.php'; + +// Global variables definitions +global $db, $langs, $user; + +// Translations +$langs->loadLangs(array("errors", "admin", "dolisirh@dolisirh")); + +// Initialize objects +// Technical objets +$modDolisirh = new modDolisirh($db); + +// Access control +if (!$user->admin) accessforbidden(); + +/* + * View + */ + +$help_url = 'FR:Module_DoliSIRH'; +$title = $langs->trans("DoliSIRHAbout"); +$morejs = array("/dolisirh/js/dolisirh.js.php"); +$morecss = array("/dolisirh/css/dolisirh.css"); + +llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss); + +// Subheader +$linkback = ''.$langs->trans("BackToModuleList").''; + +print load_fiche_titre($title, $linkback, 'object_dolisirh@dolisirh'); + +// Configuration header +$head = dolisirhAdminPrepareHead(); +print dol_get_fiche_head($head, 'about', '', 0, 'dolisirh@dolisirh'); + +print $modDolisirh->getDescLong(); + +// Page end +print dol_get_fiche_end(); +llxFooter(); +$db->close(); diff --git a/admin/index.php b/admin/index.php new file mode 100644 index 0000000..17927e6 --- /dev/null +++ b/admin/index.php @@ -0,0 +1,2 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file admin/project.php + * \ingroup dolisirh + * \brief DoliSIRH project/task config page. + */ + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +// Try main.inc.php using relative path +if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; +if (!$res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; +if (!$res) die("Include of main fails"); + +// Libraries +require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; +require_once DOL_DOCUMENT_ROOT . "/core/class/html.formother.class.php"; +require_once DOL_DOCUMENT_ROOT . "/core/class/html.formprojet.class.php"; + +require_once '../lib/dolisirh.lib.php'; + +// Global variables definitions +global $conf, $db, $langs, $user; + +// Translations +$langs->loadLangs(array("errors", "admin", "dolisirh@dolisirh")); + +// Parameters +$action = GETPOST('action', 'alpha'); +$backtopage = GETPOST('backtopage', 'alpha'); + +// Initialize objects +// View objets +$form = new Form($db); +$formother = new FormOther($db); +$formproject = new FormProjets($db); + +// Access control +if (!$user->admin) accessforbidden(); + +/* + * Actions + */ + +if ($action == 'update') { + $HRProject = GETPOST('HRProject', 'none'); + $HRProject = explode('_', $HRProject); + + dolibarr_set_const($db, "DOLISIRH_HR_PROJECT", $HRProject[0], 'integer', 0, '', $conf->entity); + setEventMessages($langs->transnoentities('TicketProjectUpdated'), array()); + header("Location: " . $_SERVER["PHP_SELF"]); + exit; +} + +if ($action == 'updateThemeColor') { + $val = (implode(',', (colorStringToArray(GETPOST('DOLISIRH_EXCEEDED_TIME_SPENT_COLOR'), array())))); + if ($val == '') { + dolibarr_del_const($db, 'DOLISIRH_EXCEEDED_TIME_SPENT_COLOR', $conf->entity); + } else { + dolibarr_set_const($db, 'DOLISIRH_EXCEEDED_TIME_SPENT_COLOR', $val, 'chaine', 0, '', $conf->entity); + } + + $val = (implode(',', (colorStringToArray(GETPOST('DOLISIRH_NOT_EXCEEDED_TIME_SPENT_COLOR'), array())))); + if ($val == '') { + dolibarr_del_const($db, 'DOLISIRH_NOT_EXCEEDED_TIME_SPENT_COLOR', $conf->entity); + } else { + dolibarr_set_const($db, 'DOLISIRH_NOT_EXCEEDED_TIME_SPENT_COLOR', $val, 'chaine', 0, '', $conf->entity); + } + + $val = (implode(',', (colorStringToArray(GETPOST('DOLISIRH_PERFECT_TIME_SPENT_COLOR'), array())))); + if ($val == '') { + dolibarr_del_const($db, 'DOLISIRH_PERFECT_TIME_SPENT_COLOR', $conf->entity); + } else { + dolibarr_set_const($db, 'DOLISIRH_PERFECT_TIME_SPENT_COLOR', $val, 'chaine', 0, '', $conf->entity); + } +} + +/* + * View + */ + +$help_url = 'FR:Module_DoliSIRH'; +$title = $langs->trans("ProjectsAndTasks"); +$morejs = array("/dolisirh/js/dolisirh.js.php"); +$morecss = array("/dolisirh/css/dolisirh.css"); + +llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss); + +// Subheader +$linkback = ''.$langs->trans("BackToModuleList").''; + +print load_fiche_titre($title, $linkback, 'object_dolisirh@dolisirh'); + +// Configuration header +$head = dolisirhAdminPrepareHead(); +print dol_get_fiche_head($head, 'projecttasks', '', -1, 'dolisirh@dolisirh'); + +// Project +print load_fiche_titre($langs->transnoentities("HRProject"), '', 'project'); + +print '
'; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +if ( ! empty($conf->projet->enabled)) { + $langs->load("projects"); + print ''; +} + +print '
' . $langs->transnoentities("Name") . '' . $langs->transnoentities("SelectProject") . '' . $langs->transnoentities("Action") . '
'; + $formproject->select_projects(-1, (GETPOST('projectid')) ? GETPOST('projectid') : $conf->global->DOLISIRH_HR_PROJECT, 'HRProject', 0, 0, 0, 0, 0, 0, 0, '', 0, 0, 'maxwidth500'); + print ' '; + print ''; + print '
'; +print '
'; + +//Time spent +print load_fiche_titre($langs->transnoentities("TimeSpent"), '', 'clock'); + +print ''; + +print ''; +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; + +print '
' . $langs->transnoentities("Parameters") . '' . $langs->transnoentities("Description") . '' . $langs->transnoentities("Status") . '
'; +print $langs->transnoentities("SpendMoreTimeThanPlanned"); +print ''; +print $langs->transnoentities("SpendMoreTimeThanPlannedDescription"); +print ''; +print ajax_constantonoff('DOLISIRH_SPEND_MORE_TIME_THAN_PLANNED'); +print '
'; + +//Theme dashboard time spent +print load_fiche_titre($langs->transnoentities("ThemeDashboardTimeSpent"), '', 'clock'); + +print '
'; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; + +print '
' . $langs->transnoentities("Parameters") . '' . $langs->transnoentities("Value") . '
'.$langs->trans("ExceededTimeSpentColor").''; +print $formother->selectColor(colorArrayToHex(colorStringToArray((!empty($conf->global->DOLISIRH_EXCEEDED_TIME_SPENT_COLOR) ? $conf->global->DOLISIRH_EXCEEDED_TIME_SPENT_COLOR : ''), array()), ''), 'DOLISIRH_EXCEEDED_TIME_SPENT_COLOR', '', 1, '', '', 'dolisirhexceededtimespentcolor'); +print ''.$langs->trans("Default").': #FF0000'; +print '
'.$langs->trans("NotExceededTimeSpentColor").''; +print $formother->selectColor(colorArrayToHex(colorStringToArray((!empty($conf->global->DOLISIRH_NOT_EXCEEDED_TIME_SPENT_COLOR) ? $conf->global->DOLISIRH_NOT_EXCEEDED_TIME_SPENT_COLOR : ''), array()), ''), 'DOLISIRH_NOT_EXCEEDED_TIME_SPENT_COLOR', '', 1, '', '', 'dolisirhnotexceededtimespentcolor'); +print ''.$langs->trans("Default").': #FFA500'; +print '
'.$langs->trans("PerfectTimeSpentColor").''; +print $formother->selectColor(colorArrayToHex(colorStringToArray((!empty($conf->global->DOLISIRH_PERFECT_TIME_SPENT_COLOR) ? $conf->global->DOLISIRH_PERFECT_TIME_SPENT_COLOR : ''), array()), ''), 'DOLISIRH_PERFECT_TIME_SPENT_COLOR', '', 1, '', '', 'dolisirhperfecttimespentcolor'); +print ''.$langs->trans("Default").': #008000'; +print '
'; + +print '
'; +print ''; +print '
'; + +print '
'; + +// Page end +print dol_get_fiche_end(); +llxFooter(); +$db->close(); diff --git a/admin/setup.php b/admin/setup.php new file mode 100644 index 0000000..be062bf --- /dev/null +++ b/admin/setup.php @@ -0,0 +1,139 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file admin/setup.php + * \ingroup dolisirh + * \brief DoliSIRH setup page. + */ + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +// Try main.inc.php using relative path +if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; +if (!$res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; +if (!$res) die("Include of main fails"); + +// Libraries +require_once DOL_DOCUMENT_ROOT."/core/lib/admin.lib.php"; +require_once '../lib/dolisirh.lib.php'; + +global $conf, $db, $langs, $user; + +// Translations +$langs->loadLangs(array("admin", "dolisirh@dolisirh")); + +// Parameters +$action = GETPOST('action', 'alpha'); +$backtopage = GETPOST('backtopage', 'alpha'); + +$value = GETPOST('value', 'alpha'); + +$arrayofparameters = array( + 'DOLISIRH_DEFAUT_TICKET_TIME'=>array('css'=>'minwidth200', 'enabled'=>1), +); + +// Access control +if (!$user->admin) accessforbidden(); + +/* + * Actions + */ + +include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php'; + +require_once '../core/tpl/dolisirh_projectcreation_action.tpl.php'; + +/* + * View + */ + +$form = new Form($db); + + +$help_url = 'FR:Module_DoliSIRH'; +$title = $langs->trans("DoliSIRHSetup"); +$morejs = array("/dolisirh/js/dolisirh.js.php"); +$morecss = array("/dolisirh/css/dolisirh.css"); + +llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss); + +// Subheader +$linkback = ''.$langs->trans("BackToModuleList").''; + +print load_fiche_titre($title, $linkback, 'dolisirh@dolisirh'); + +// Configuration header +$head = dolisirhAdminPrepareHead(); +print dol_get_fiche_head($head, 'settings', '', -1, "dolisirh@dolisirh"); + +// Setup page goes here +echo ''.$langs->trans("DoliSIRHSetupPage").'

'; + +if ($action == 'edit') { + print '
'; + print ''; + print ''; + + print ''; + print ''; + + foreach ($arrayofparameters as $key => $val) { + print ''; + } + print '
'.$langs->trans("Parameter").''.$langs->trans("Value").'
'; + $tooltiphelp = (($langs->trans($key.'Tooltip') != $key.'Tooltip') ? $langs->trans($key.'Tooltip') : ''); + print $form->textwithpicto($langs->trans($key), $tooltiphelp); + print '
'; + + print '
'; + print ''; + print '
'; + + print '
'; + print '
'; +} else { + if (!empty($arrayofparameters)) { + print ''; + print ''; + + foreach ($arrayofparameters as $key => $val) { + print ''; + } + + print '
'.$langs->trans("Parameter").''.$langs->trans("Value").'
'; + $tooltiphelp = (($langs->trans($key.'Tooltip') != $key.'Tooltip') ? $langs->trans($key.'Tooltip') : ''); + print $form->textwithpicto($langs->trans($key), $tooltiphelp); + print ''.$conf->global->$key.'
'; + + print '
'; + print ''.$langs->trans("Modify").''; + print '
'; + } +} + +// Page end +print dol_get_fiche_end(); +llxFooter(); +$db->close(); diff --git a/admin/timesheet.php b/admin/timesheet.php new file mode 100644 index 0000000..e1aaf70 --- /dev/null +++ b/admin/timesheet.php @@ -0,0 +1,132 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file admin/timesheet/timesheet.php + * \ingroup dolisirh + * \brief DoliSIRH timesheet config page. + */ + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +// Try main.inc.php using relative path +if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; +if (!$res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; +if (!$res && file_exists("../../../../main.inc.php")) $res = @include "../../../../main.inc.php"; +if (!$res) die("Include of main fails"); + +// Libraries +require_once DOL_DOCUMENT_ROOT . "/core/lib/admin.lib.php"; + +require_once '../lib/dolisirh.lib.php'; +require_once '../class/timesheet.class.php'; + +// Global variables definitions +global $conf, $db, $langs, $user; + +// Load translation files required by the page +$langs->loadLangs(array("admin", "dolisirh@dolisirh")); + +// Get parameters +$action = GETPOST('action', 'alpha'); +$backtopage = GETPOST('backtopage', 'alpha'); + +// Initialize objects +// Technical objets +$timesheet = new TimeSheet($db); + +// View objects +$form = new Form($db); + +// Access control +if (!$user->admin) accessforbidden(); + +/* + * View + */ + +$help_url = 'FR:Module_DoliSIRH'; +$title = $langs->trans("TimeSheet"); +$morejs = array("/dolisirh/js/dolisirh.js.php"); +$morecss = array("/dolisirh/css/dolisirh.css"); + +llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss); + +// Subheader +$linkback = ''.$langs->trans("BackToModuleList").''; + +print load_fiche_titre($title, $linkback, 'dolisirh@dolisirh'); + +// Configuration header +$head = dolisirhAdminPrepareHead(); +print dol_get_fiche_head($head, 'timesheet', '', -1, "timesheet@dolisirh"); + +//Time spent +print load_fiche_titre($langs->transnoentities("TimeSheetData"), '', 'object_timesheet@dolisirh'); + +print ''; + +print ''; +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; + +print '
' . $langs->transnoentities("Parameters") . '' . $langs->transnoentities("Description") . '' . $langs->transnoentities("Status") . '
'; +print $langs->trans('PrefillDate'); +print ""; +print $langs->trans('PrefillDateDescription'); +print ''; +print ajax_constantonoff('DOLISIRH_TIMESHEET_PREFILL_DATE'); +print '
'; +print $langs->trans('AddAttendantsConf'); +print ""; +print $langs->trans('AddAttendantsDescription'); +print ''; +print ajax_constantonoff('DOLISIRH_TIMESHEET_ADD_ATTENDANTS'); +print '
'; +print $langs->trans('CheckDateEnd'); +print ""; +print $langs->trans('CheckDateEndDescription'); +print ''; +print ajax_constantonoff('DOLISIRH_TIMESHEET_CHECK_DATE_END'); +print '
'; + +// Page end +print dol_get_fiche_end(); +llxFooter(); +$db->close(); + diff --git a/admin/timesheetdocument.php b/admin/timesheetdocument.php new file mode 100644 index 0000000..7968ff2 --- /dev/null +++ b/admin/timesheetdocument.php @@ -0,0 +1,331 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file admin/timesheetdocument/timesheetdocument.php + * \ingroup dolisirh + * \brief DoliSIRH timesheetdocument config page. + */ + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +// Try main.inc.php using relative path +if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; +if (!$res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; +if (!$res && file_exists("../../../../main.inc.php")) $res = @include "../../../../main.inc.php"; +if (!$res) die("Include of main fails"); + +// Libraries +require_once DOL_DOCUMENT_ROOT . "/core/lib/admin.lib.php"; + +require_once '../lib/dolisirh.lib.php'; + +// Global variables definitions +global $conf, $db, $langs, $user; + +// Load translation files required by the page +$langs->loadLangs(array("admin", "dolisirh@dolisirh")); + +// Get parameters +$action = GETPOST('action', 'alpha'); +$value = GETPOST('value', 'alpha'); +$type = GETPOST('type', 'alpha'); +$const = GETPOST('const', 'alpha'); +$label = GETPOST('label', 'alpha'); + +// Initialize objects +// View objects +$form = new Form($db); + +// Access control +if (!$user->admin) accessforbidden(); + +/* + * Actions + */ + +// Activate a model +if ($action == 'set') { + addDocumentModel($value, $type, $label, $const); + header("Location: " . $_SERVER["PHP_SELF"]); +} elseif ($action == 'del') { + delDocumentModel($value, $type); + header("Location: " . $_SERVER["PHP_SELF"]); +} + +// Set default model Or set numering module +if ($action == 'setdoc') { + $constforval = "DOLISIRH_TIMESHEETDOCUMENT_DEFAULT_MODEL"; + $label = ''; + + if (dolibarr_set_const($db, $constforval, $value, 'chaine', 0, '', $conf->entity)) { + $conf->global->$constforval = $value; + } + + // On active le model + $ret = delDocumentModel($value, $type); + if ($ret > 0) { + $ret = addDocumentModel($value, $type, $label); + } +} elseif ($action == 'setmod') { + $constforval = 'DOLISIRH_'.strtoupper($type)."_ADDON"; + dolibarr_set_const($db, $constforval, $value, 'chaine', 0, '', $conf->entity); +} + +/* + * View + */ + +$help_url = 'FR:Module_DoliSIRH'; +$title = $langs->trans("TimeSheetDocument"); +$morejs = array("/dolisirh/js/dolisirh.js.php"); +$morecss = array("/dolisirh/css/dolisirh.css"); + +llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss); + +// Subheader +$linkback = ''.$langs->trans("BackToModuleList").''; + +print load_fiche_titre($title, $linkback, 'dolisirh@dolisirh'); + +// Configuration header +$head = dolisirhAdminPrepareHead(); +print dol_get_fiche_head($head, 'timesheetdocument', '', -1, "dolisirh@dolisirh"); + +$types = array( + 'TimeSheetDocument' => 'timesheetdocument' +); + +$pictos = array( + 'TimeSheetDocument' => ' ' +); + +foreach ($types as $type => $documentType) { + print load_fiche_titre($pictos[$type] . $langs->trans($type), '', ''); + print '
'; + + $trad = 'DoliSIRH' . $type . 'DocumentNumberingModule'; + print load_fiche_titre($langs->trans($trad), '', ''); + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + clearstatcache(); + $dir = dol_buildpath("/custom/dolisirh/core/modules/dolisirh/".$documentType."/"); + if (is_dir($dir)) { + $handle = opendir($dir); + if (is_resource($handle)) { + while (($file = readdir($handle)) !== false ) { + if (!is_dir($dir.$file) || (substr($file, 0, 1) <> '.' && substr($file, 0, 3) <> 'CVS')) { + $filebis = $file; + + $classname = preg_replace('/\.php$/', '', $file); + $classname = preg_replace('/\-.*$/', '', $classname); + + if (!class_exists($classname) && is_readable($dir.$filebis) && (preg_match('/mod_/', $filebis) || preg_match('/mod_/', $classname)) && substr($filebis, dol_strlen($filebis) - 3, 3) == 'php') { + // Charging the numbering class + require_once $dir.$filebis; + + $module = new $classname($db); + + if ($module->isEnabled()) { + print ''; + + // Show example of numbering module + print ''; + + print ''; + + // Example for timesheet + $htmltooltip = '' . $langs->trans("Version") . ': ' . $module->getVersion() . '
'; + $nextval = $module->getNextValue($module); + if ("$nextval" != $langs->trans("NotAvailable")) { // Keep " on nextval + $htmltooltip .= $langs->trans("NextValue").': '; + if ($nextval) { + if (preg_match('/^Error/', $nextval) || $nextval == 'NotConfigured') + $nextval = $langs->trans($nextval); + $htmltooltip .= $nextval.'
'; + } else { + $htmltooltip .= $langs->trans($module->error).'
'; + } + } + + print ''; + print ""; + } + } + } + } + closedir($handle); + } + } + + /* + * Documents models for TimeSheet + */ + $trad = "DoliSIRHTemplateDocument" . $type; + print load_fiche_titre($langs->trans($trad), '', ''); + + // Define models table + $def = array(); + $sql = "SELECT nom"; + $sql .= " FROM ".MAIN_DB_PREFIX."document_model"; + $sql .= " WHERE type = '".$documentType."'"; + $sql .= " AND entity = ".$conf->entity; + $resql = $db->query($sql); + if ($resql) { + $i = 0; + $num_rows = $db->num_rows($resql); + while ($i < $num_rows) { + $array = $db->fetch_array($resql); + $def[] = $array[0]; + $i++; + } + } + else { + dol_print_error($db); + } + + print '
'.$langs->trans("Name").''.$langs->trans("Description").''.$langs->trans("Example").''.$langs->trans("Status").''.$langs->trans("ShortInfo").'
'; + print $langs->trans($module->name); + print ""; + print $module->info(); + print ''; + $tmp = $module->getExample(); + if (preg_match('/^Error/', $tmp)) print '
'.$langs->trans($tmp).'
'; + elseif ($tmp == 'NotConfigured') print $langs->trans($tmp); + else print $tmp; + print '
'; + $confType = 'DOLISIRH_' . strtoupper($documentType) . '_ADDON'; + if ($conf->global->$confType == $file || $conf->global->$confType.'.php' == $file) { + print img_picto($langs->trans("Activated"), 'switch_on'); + } + else { + print ''.img_picto($langs->trans("Disabled"), 'switch_off').''; + } + print ''; + print $form->textwithpicto('', $htmltooltip, 1, 0); + if ($conf->global->$confType.'.php' == $file) { // If module is the one used, we show existing errors + if (!empty($module->error)) dol_htmloutput_mesg($module->error, '', 'error', 1); + } + print '
'; + print ''; + print ''; + print ''; + print '"; + print '"; + print ''; + print ''; + print ""; + + clearstatcache(); + $dir = dol_buildpath("/custom/dolisirh/core/modules/dolisirh/".$documentType."/"); + if (is_dir($dir)) { + $handle = opendir($dir); + if (is_resource($handle)) { + while (($file = readdir($handle)) !== false) { + $filelist[] = $file; + } + closedir($handle); + arsort($filelist); + + foreach ($filelist as $file) { + if (preg_match('/\.modules\.php$/i', $file) && preg_match('/^(pdf_|doc_)/', $file)) { + if (file_exists($dir.'/'.$file)) { + $name = substr($file, 4, dol_strlen($file) - 16); + $classname = substr($file, 0, dol_strlen($file) - 12); + + require_once $dir.'/'.$file; + $module = new $classname($db); + + print ''; + + // Active + print '"; + + // Default + print ''; + + // Info + $htmltooltip = ''.$langs->trans("Name").': '.$module->name; + $htmltooltip .= '
'.$langs->trans("Type").': '.($module->type ?: $langs->trans("Unknown")); + $htmltooltip .= '
'.$langs->trans("Width").'/'.$langs->trans("Height").': '.$module->page_largeur.'/'.$module->page_hauteur; + $htmltooltip .= '

'.$langs->trans("FeaturesSupported").':'; + $htmltooltip .= '
'.$langs->trans("Logo").': '.yn($module->option_logo, 1, 1); + print ''; + + // Preview + print ''; + print ''; + } + } + } + } + } + + print '
'.$langs->trans("Name").''.$langs->trans("Description").''.$langs->trans("Status")."'.$langs->trans("Default")."'.$langs->trans("ShortInfo").''.$langs->trans("Preview").'
'; + print (empty($module->name) ? $name : $module->name); + print ""; + if (method_exists($module, 'info')) print $module->info($langs); + else print $module->description; + print ''; + if (in_array($name, $def)) { + print 'scandir.'&label='.urlencode($module->name).'&type='. explode('_', $documentType)[0].'">'; + print img_picto($langs->trans("Enabled"), 'switch_on'); + print ''; + } + else { + print 'scandir.'&label='.urlencode($module->name).'&type='. explode('_', $documentType)[0].'">'.img_picto($langs->trans("Disabled"), 'switch_off').''; + } + print "'; + $defaultModelConf = 'DOLISIRH_' . strtoupper($documentType) . '_DEFAULT_MODEL'; + if ($conf->global->$defaultModelConf == $name) { + print img_picto($langs->trans("Default"), 'on'); + } + else { + print 'scandir.'&label='.urlencode($module->name).'">'.img_picto($langs->trans("Disabled"), 'off').''; + } + print ''; + print $form->textwithpicto('', $htmltooltip, -1, 0); + print ''; + if ($module->type == 'pdf') { + print ''.img_object($langs->trans("Preview"), 'pdf').''; + } + else { + print img_object($langs->trans("PreviewNotAvailable"), 'generic'); + } + print '
'; +} + +// Page end +print dol_get_fiche_end(); +llxFooter(); +$db->close(); + diff --git a/build/index.php b/build/index.php new file mode 100644 index 0000000..17927e6 --- /dev/null +++ b/build/index.php @@ -0,0 +1,2 @@ + +# Author: Copyright - +# License: GPLv3 +# Install: Just unpack content of module package in Dolibarr directory. +# Setup: Go on Dolibarr setup - modules to enable module. +# +# Files in module +mymodule/ \ No newline at end of file diff --git a/class/actions_dolisirh.class.php b/class/actions_dolisirh.class.php new file mode 100644 index 0000000..fab02b5 --- /dev/null +++ b/class/actions_dolisirh.class.php @@ -0,0 +1,935 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file class/actions_dolisirh.class.php + * \ingroup dolisirh + * \brief DoliSIRH hook overload. + */ + +/** + * Class ActionsDolisirh + */ +class ActionsDolisirh +{ + /** + * @var DoliDB Database handler. + */ + public $db; + + /** + * @var string Error code (or message) + */ + public $error = ''; + + /** + * @var array Errors + */ + public $errors = array(); + + /** + * @var array Hook results. Propagated to $hookmanager->resArray for later reuse + */ + public $results = array(); + + /** + * @var string String displayed by executeHook() immediately after return + */ + public $resprints; + + /** + * Constructor + * + * @param DoliDB $db Database handler + */ + public function __construct(DoliDB $db) + { + $this->db = $db; + } + + /** + * Overloading the doActions function : replacing the parent's function with the one below + * + * @param array $parameters Hook metadata (context, etc...) + * @param object $object The object to process + * @param string $action Current action (if set). Generally create or edit or null + * @return int 0 < on error, 0 on success, 1 to replace standard code + */ + public function doActions(array $parameters, object $object, string $action): int + { + require_once DOL_DOCUMENT_ROOT.'/core/modules/project/task/mod_task_simple.php'; + + global $langs; + + $error = 0; // Error counter + + if (in_array($parameters['currentcontext'], array('invoicecard'))) { + // Action that will be done after pressing the button + if ($action == 'createtask-dolisirh') { + + // Start + // Variable : ref + // Description : create the ref of the task + $mod = new mod_task_simple; + $ref = $mod->getNextValue(0, ""); + // End + + //Start + //Variable : label + //Description : creation of the label of the task + + //Contruction de la chaine de caractère sur le modèle AAAAMMJJ-nomprojet-tag + //Variable : datef = Date de début de période de facturation + $query = "SELECT datef, ref FROM ".MAIN_DB_PREFIX."facture"; + $result = $this->db->query($query); + while ($row = $result->fetch_array()) { + if ($row['ref'] == $object->ref) { + $datef_invoice[0] = $row['datef']; + } + } + $datef_invoice = explode('-', $datef_invoice[0]); + $datef = implode($datef_invoice); + //datef + + // Contruction de la chaine de caractère REGEX : AAAAMMJJ-nomprojet-tag + // Wording retrieval + $fk_projet_fac = $object->fk_project; + $query = "SELECT rowid, title FROM ".MAIN_DB_PREFIX."projet"; + $result = $this->db->query($query); + while ($row = $result->fetch_array()) { + if ($row['rowid'] == $object->fk_project) { + $title[0] = $row['title']; + } + } + $wording = $title[0]; + + //Tag retrieval + //@todo REGEX à construire dans les réglages dans notre cas : DATEDEBUTPERIODE-NOMPROJET-TAGS EX: 20200801-eoxia.fr-ref + $query = "SELECT ref, fk_projet FROM ".MAIN_DB_PREFIX."facture"; + $result = $this->db->query($query); + while ($row = $result->fetch_array()) { + if ($row['ref'] == $object->ref) { + $invoice_fk_projet[0] = $row['fk_projet']; + } + } + $query = "SELECT fk_project, fk_categorie FROM ".MAIN_DB_PREFIX."categorie_project"; + $result = $this->db->query($query); + while ($row = $result->fetch_array()) { + if ($row['fk_project'] == $invoice_fk_projet[0]) { + $fk_categorie[0] = $row['fk_categorie']; + } + } + $query = "SELECT rowid, label FROM ".MAIN_DB_PREFIX."categorie"; + $result = $this->db->query($query); + while ($row = $result->fetch_array()) { + if ($row['rowid'] == $fk_categorie[0]) { + $tag[0] = $row['label']; + } + } + //Concatenation of the date, wording and tag to obtain the label + $label = $datef . '-' . $wording . '-' . $tag[0]; + //End + + //Start + //Variable : fk_projet + //Description : take the fk_projet from the invoice + $fk_projet = $object->fk_project; + //End + + //Start + //Variable : dateo + //Decription : retrieval of the start date of the invoice + $i = 0; + $query = "SELECT fk_facture, date_start, date_end FROM ".MAIN_DB_PREFIX."facturedet"; + $result = $this->db->query($query); + while ($row = $result->fetch_array()) { + if ($row['fk_facture'] == $object->lines[0]->fk_facture) { + $date_start[$i] = $row['date_start']; + } + } + $dateo = $date_start[0]; + //End + + //Start + //Variable : datee + //Description : retrieval of the end date of the invoice + $i = 0; + $query = "SELECT fk_facture, date_start, date_end FROM ".MAIN_DB_PREFIX."facturedet"; + $result = $this->db->query($query); + while ($row = $result->fetch_array()) { + if ($row['fk_facture'] == $object->lines[0]->fk_facture) { + $date_end[$i] = $row['date_end']; + $i += 1; + } + } + $datee = $date_end[0]; + //End + + //Start + //Variable : planned_workload + //Description : time calculation of the planned workload + //We recover all the products from the invoice + $i = 0; + //We recover the quantity of all the products + $query = "SELECT fk_facture, fk_product, qty FROM ".MAIN_DB_PREFIX."facturedet"; + $result = $this->db->query($query); + while ($row = $result->fetch_array()) { + if ($row['fk_facture'] == $object->lines[0]->fk_facture) { + $fk_product[$i] = $row['fk_product']; + $fk_quantity[$i] = $row['qty']; + $i += 1; + } + } + $i = 0; + $j = 0; + //We recover the time of each product + $query = "SELECT rowid, duration FROM ".MAIN_DB_PREFIX."product"; + $result = $this->db->query($query); + while ($row = $result->fetch_array()) { + while (isset($fk_product[$i])) { + if ($row['rowid'] == $fk_product[$i]) { + $duration[$i] = $row['duration']; + $i += 1; + } + $i += 1; + } + $i = 0; + } + $i = 0; + $j = 0; + // We transform time into seconds + while (isset($duration[$i])) { + while (isset($duration[$i][$j])) { + if ($duration[$i][$j] == 's') { + $duration[$i] = substr($duration[$i], 0, -1); + $duration[$i] *= 1; + } elseif ($duration[$i][$j] == 'i') { + $duration[$i] = substr($duration[$i], 0, -1); + $duration[$i] *= 60; + } elseif ($duration[$i][$j] == 'h') { + $duration[$i] = substr($duration[$i], 0, -1); + $duration[$i] *= 3600; + } elseif ($duration[$i][$j] == 'd') { + $duration[$i] = substr($duration[$i], 0, -1); + $duration[$i] *= 86400; + } elseif ($duration[$i][$j] == 'w') { + $duration[$i] = substr($duration[$i], 0, -1); + $duration[$i] *= 604800; + } elseif ($duration[$i][$j] == 'm') { + $duration[$i] = substr($duration[$i], 0, -1); + $duration[$i] *= 2592000; + } elseif ($duration[$i][$j] == 'y') { + $duration[$i] = substr($duration[$i], 0, -1); + $duration[$i] *= 31104000; + } + $j += 1; + } + $i += 1; + $j = 0; + } + $i = 0; + //We multiply the time by the duration + while (isset($duration[$i])) { + if (is_int($duration[$i])) { + $duration[$i] *= intval($fk_quantity[$i]); + } + $i += 1; + } + $i = 0; + //We add all the time to all the products + $planned_workload = 0; + while (isset($duration[$i])) { + $planned_workload += intval($duration[$i]); + $i += 1; + } + //End + + //Check if the invoice is already linked to the task + $error_button = 0; + $query = "SELECT fk_facture_name FROM ".MAIN_DB_PREFIX."projet_task_extrafields"; + $result = $this->db->query($query); + while ($row = $result->fetch_array()) { + if ($row['fk_facture_name'] == $object->id) { + $error_button = 1; + } + } + //Start + //Filling of the llx_projet_task table with the variables to create the task + if ($error_button == 0) { + if (isset($fk_projet) && $planned_workload != 0 && isset($dateo) && isset($datee)) { + $req = 'INSERT INTO '.MAIN_DB_PREFIX.'projet_task(ref, fk_projet, label, dateo, datee, planned_workload) VALUES("'.$ref.'", '.intval($fk_projet).', "'.$label.'", "'.$dateo.'", "'.$datee.'", '.intval($planned_workload).')'; + $this->db->query($req); + $query = "SELECT rowid, ref, fk_projet FROM ".MAIN_DB_PREFIX."projet_task"; + $result = $this->db->query($query); + while ($row = $result->fetch_array()) { + if ($row['rowid']) { + $rowid_last_task[0] = $row['rowid']; + } + if ($row['ref']) { + $ref_last_task[0] = $row['ref']; + } + } + //Filling of the llx_projet_task_extrafields table + $req = 'INSERT INTO '.MAIN_DB_PREFIX.'projet_task_extrafields(fk_object, fk_facture_name) VALUES('.$rowid_last_task[0].', '.$object->lines[0]->fk_facture.')'; + $this->db->query($req); + //Filling of the llx_facture_extrafields table + $req = 'INSERT INTO '.MAIN_DB_PREFIX.'facture_extrafields(fk_object, fk_task) VALUES('.$object->lines[0]->fk_facture.', '.$rowid_last_task[0].')'; + $this->db->query($req); + setEventMessages($langs->trans("MessageInfo").' : '.''.$ref.'', null, 'mesgs'); + } + //Error messages + else { + if (!isset($fk_projet)) { + setEventMessages($langs->trans("MessageInfoNoCreateProject"), null, 'errors'); + } + if ($planned_workload == 0) { + setEventMessages($langs->trans("MessageInfoNoCreateTime"), null, 'errors'); + } + if (!isset($datee) || !isset($dateo)) { + setEventMessages($langs->trans("MessageInfoNoCreatedate"), null, 'errors'); + } + } + } + //End + } + } + + if (!$error) { + $this->results = array('myreturn' => 999); + $this->resprints = 'A text to show'; + return 0; // or return 1 to replace standard code + } else { + $this->errors[] = 'Error message'; + return -1; + } + } + + /** + * Overloading the addMoreActionsButtons function : replacing the parent's function with the one below + * + * @param array $parameters Hook metadata (context, etc...) + * @param object $object The object to process + * @return int 0 < on error, 0 on success, 1 to replace standard code + */ + public function addMoreActionsButtons(array $parameters, object $object): int + { + global $langs; + + $error = 0; // Error counter + + if (in_array('invoicecard', explode(':', $parameters['context']))) + { + //Creation of the link that will be sendid + if ( isset( $_SERVER['HTTPS'] ) ) { + if ( $_SERVER['HTTPS'] == 'on' ) { + $server_protocol = 'https'; + } else { + $server_protocol = 'http'; + } + } else { + $server_protocol = 'http'; + } + $actual_link = $server_protocol . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; + $actual_link .= '&action=createtask-dolisirh'; //Action + + //Check if the invoice is already linked to the task + $error_button = 0; + $query = "SELECT fk_facture_name FROM ".MAIN_DB_PREFIX."projet_task_extrafields"; + $result = $this->db->query($query); + while ($row = $result->fetch_array()) { + if ($row['fk_facture_name'] == $object->id) { + $error_button = 1; + } + } + //Check for grey button + //Start + + //Check date + $i = 0; + $query = "SELECT fk_facture, date_start, date_end FROM ".MAIN_DB_PREFIX."facturedet"; + $result = $this->db->query($query); + while ($row = $result->fetch_array()) { + if ($row['fk_facture'] == $object->lines[0]->fk_facture) { + $date_end[$i] = $row['date_end']; + $date_start[$i] = $row['date_start']; + $i += 1; + } + } + $datee = $date_end[0]; + $dateo = $date_start[0]; + + //Check service time + $i = 0; + $query = "SELECT fk_facture, fk_product, qty FROM ".MAIN_DB_PREFIX."facturedet"; + $result = $this->db->query($query); + while ($row = $result->fetch_array()) { + if ($row['fk_facture'] == $object->lines[0]->fk_facture) { + $fk_product[$i] = $row['fk_product']; + $fk_quantity[$i] = $row['qty']; + $i += 1; + } + } + $i = 0; + $j = 0; + $query = "SELECT rowid, duration FROM ".MAIN_DB_PREFIX."product"; + $result = $this->db->query($query); + while ($row = $result->fetch_array()) { + while (isset($fk_product[$i])) { + if ($row['rowid'] == $fk_product[$i]) { + $duration[$i] = $row['duration']; + $i += 1; + } + $i += 1; + } + $i = 0; + } + $i = 0; + $j = 0; + while (isset($duration[$i])) { + while (isset($duration[$i][$j])) { + if ($duration[$i][$j] == 's') { + $duration[$i] = substr($duration[$i], 0, -1); + $duration[$i] *= 1; + } elseif ($duration[$i][$j] == 'i') { + $duration[$i] = substr($duration[$i], 0, -1); + $duration[$i] *= 60; + } elseif ($duration[$i][$j] == 'h') { + $duration[$i] = substr($duration[$i], 0, -1); + $duration[$i] *= 3600; + } elseif ($duration[$i][$j] == 'd') { + $duration[$i] = substr($duration[$i], 0, -1); + $duration[$i] *= 86400; + } elseif ($duration[$i][$j] == 'w') { + $duration[$i] = substr($duration[$i], 0, -1); + $duration[$i] *= 604800; + } elseif ($duration[$i][$j] == 'm') { + $duration[$i] = substr($duration[$i], 0, -1); + $duration[$i] *= 2592000; + } elseif ($duration[$i][$j] == 'y') { + $duration[$i] = substr($duration[$i], 0, -1); + $duration[$i] *= 31104000; + } + $j += 1; + } + $i += 1; + $j = 0; + } + $i = 0; + while (isset($duration[$i])) { + if (is_int($duration[$i])) { + $duration[$i] *= intval($fk_quantity[$i]); + } + $i += 1; + } + $i = 0; + $planned_workload = 0; + while (isset($duration[$i])) { + $planned_workload += intval($duration[$i]); + $i += 1; + } + //End + + //Button + if ($error_button == 0) { + if (isset($object->fk_project) && isset($dateo) && isset($datee) && $planned_workload != 0) { + print ''; + } elseif (!isset($object->fk_project)) { + print ''; + } elseif (!isset($dateo)) { + print ''; + } elseif (!isset($datee)) { + print ''; + } elseif ($planned_workload == 0) { + print ''; + } + } + } + + if (!$error) { + return 0; // or return 1 to replace standard code + } else { + $this->errors[] = 'Error message'; + return -1; + } + } + + /** + * Overloading the printCommonFooter function : replacing the parent's function with the one below + * + * @param array $parameters Hook metadata (context, etc...) + * @throws Exception + */ + public function printCommonFooter(array $parameters) + { + global $conf, $user, $langs; + $langs->load('projects'); + if (in_array('ticketcard', explode(':', $parameters['context']))) { + if (GETPOST('action') == 'presend_addmessage') { + $ticket = new Ticket($this->db); + $result = $ticket->fetch('',GETPOST('ref','alpha'),GETPOST('track_id','alpha')); + dol_syslog(var_export($ticket, true), LOG_DEBUG); + if ($result > 0 && ($ticket->id) > 0) { + if ( is_array($ticket->array_options) && array_key_exists('options_fk_task',$ticket->array_options) && $ticket->array_options['options_fk_task']>0) { ?> + + trans('MessageNoTaskLink'),'warnings'); + } + } else { + setEventMessages($ticket->error,$ticket->errors,'errors'); + } + dol_htmloutput_events(); + } else if ((GETPOST('action') == '' || empty(GETPOST('action')) || GETPOST('action') == 'view')) { + require_once __DIR__ . '/../../../projet/class/task.class.php'; + + $task = new Task($this->db); + $ticket = new Ticket($this->db); + + $ticket->fetch(GETPOST('id')); + $ticket->fetch_optionals(); + + $task_id = $ticket->array_options['options_fk_task']; + + $task->fetch($task_id); + + if (!empty($task_id) && $task_id > 0) { ?> + + id); + } + + if (isTaskFavorite(GETPOST('id'), $user->id)) { + $favoriteStar = ''; + } else { + $favoriteStar = ''; + } + ?> + + getTasksArray(0, 0, GETPOST('id')); + if (is_array($tasksarray) && !empty($tasksarray)) { + foreach ($tasksarray as $linked_task) { + if (isTaskFavorite($linked_task->id, $user->id)) { + $favoriteStar = ''; + } else { + $favoriteStar = ''; + } + ?> + + getTasksArray(0, 0, GETPOST('id')); + + if (is_array($tasksarray) && !empty($tasksarray)) { + foreach ($tasksarray as $linked_task) { + if (isTaskFavorite($linked_task->id, $user->id)) { + $favoriteStar = ''; + } else { + $favoriteStar = ''; + } + ?> + + db); + + $invoice_id = GETPOST('facid'); + + // Categories + if ($conf->categorie->enabled) { + $html = ''.$langs->trans("Categories").''; + $html .= $form->showCategories($invoice_id, 'invoice', 1); + $html .= ''; ?> + ; + '; + } + if (GETPOST('action') == 'toggleTaskFavorite') { + toggleTaskFavorite(GETPOST('taskId'), $user->id); + } + ?> + + array( + 'id' => 436370001, + 'code' => 'invoice', + 'obj_class' => 'Facture', + 'obj_table' => 'facture', + ), + 'invoicerec' => array( + 'id' => 436370002, + 'code' => 'invoicerec', + 'obj_class' => 'Facture', + 'obj_table' => 'facture', + ), + 'timesheet' => array( + 'id' => 436370003, + 'code' => 'timesheet', + 'obj_class' => 'TimeSheet', + 'obj_table' => 'dolisirh_timesheet', + ) + ); + + $this->results = $tags; + } + } + + /** + * Overloading the formObjectOptions function : replacing the parent's function with the one below + * + * @param array $parameters Hook metadata (context, etc...) + * @param object $object Object + * @param string $action Current action (if set). Generally create or edit or null + */ + public function formObjectOptions(array $parameters, object $object, string $action) + { + global $conf, $langs; + + if ($parameters['currentcontext'] == 'invoicecard') { + require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php'; + + $form = new Form($this->db); + + if ($action == 'create') { + if (!empty($conf->categorie->enabled)) { + // Categories + print '' . $langs->trans("Categories") . ''; + $cate_arbo = $form->select_all_categories('invoice', '', 'parent', 64, 0, 1); + print img_picto('', 'category') . $form->multiselectarray('categories', $cate_arbo, GETPOST('categories', 'array'), '', 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0); + print ""; + } + } else if ($action == 'edit') { +// // Tags-Categories +// if ($conf->categorie->enabled) { +// print ''.$langs->trans("Categories").''; +// $cate_arbo = $form->select_all_categories('invoice', '', 'parent', 64, 0, 1); +// $c = new Categorie($this->db); +// $cats = $c->containing($object->id, 'invoice'); +// $arrayselected = array(); +// if (is_array($cats)) { +// foreach ($cats as $cat) { +// $arrayselected[] = $cat->id; +// } +// } +// print img_picto('', 'category').$form->multiselectarray('categories', $cate_arbo, $arrayselected, '', 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0); +// print ""; +// } + } else if ($action == '') { + // Categories + if ($conf->categorie->enabled) { + print ''.$langs->trans("Categories").''; + print $form->showCategories($object->id, 'invoice', 1); + print ""; + } + } + } + if ($parameters['currentcontext'] == 'invoicereccard') { + require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php'; + + $form = new Form($this->db); + + if ($action == '') { + // Categories + if ($conf->categorie->enabled) { + print ''.$langs->trans("Categories").''; + print $form->showCategories($object->id, 'invoicerec', 1); + print ""; + } + } + } + } + + /** + * Overloading the afterCreationOfRecurringInvoice function : replacing the parent's function with the one below + * + * @param array $parameters Hook metadata (context, etc...) + * @param object $object Object + */ + public function afterCreationOfRecurringInvoice(array $parameters, object $object) { + if (in_array($parameters['currentcontext'], array('cron', 'cronjoblist'))) { + require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php'; + require_once __DIR__ . '/../lib/dolisirh_function.lib.php'; + + $cat = new Categorie($this->db); + + $categories = $cat->containing($parameters['facturerec']->id, 'invoicerec'); + if (is_array($categories) && !empty($categories)) { + foreach ($categories as $category) { + $categoryArray[] = $category->id; + } + if (!empty($categoryArray)) { + setCategoriesObject($categoryArray, 'invoice', false, $object); + } + } + } + } + + /** + * Overloading the printObjectLine function : replacing the parent's function with the one below + * + * @param array $parameters Hook metadata (context, etc...) + */ + public function printObjectLine(array $parameters) { + if ($parameters['currentcontext'] == 'timesheetcard') { + if ($parameters['line']->fk_product > 0) { + require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; + + $product = new Product($this->db); + + $product->fetch($parameters['line']->fk_product); + $parameters['line']->ref = $product->ref; + $parameters['line']->label = $product->label; + $parameters['line']->product_label = $product->label; + $parameters['line']->description = $product->description; + } + } + } + + /** + * Overloading the deleteFile function : replacing the parent's function with the one below + * + * @param array $parameters Hook metadata (context, etc...) + * @param object $object Object + * @throws Exception + */ + public function deleteFile(array $parameters, $object) { + if ($parameters['currentcontext'] == 'timesheetcard' && !preg_match('/signature/', $parameters['file'])) { + global $user; + + require_once DOL_DOCUMENT_ROOT . '/projet/class/task.class.php'; + + $signatory = new TimeSheetSignature($this->db); + $usertmp = new User($this->db); + $task = new Task($this->db); + + $object->status = $object::STATUS_DRAFT; + $object->update($user, false); + $signatories = $signatory->fetchSignatories($object->id, 'timesheet'); + if ( ! empty($signatories) && $signatories > 0) { + foreach ($signatories as $signatory) { + $signatory->status = $signatory::STATUS_REGISTERED; + $signatory->signature = ''; + $signatory->update($user, false); + } + } + + $usertmp->fetch($object->fk_user_assign); + $filter = ' AND ptt.task_date BETWEEN ' . "'" .dol_print_date($object->date_start, 'dayrfc') . "'" . ' AND ' . "'" . dol_print_date($object->date_end, 'dayrfc'). "'"; + $alltimespent = $task->fetchAllTimeSpent($usertmp, $filter); + foreach ($alltimespent as $timespent) { + $task->fetchObjectLinked(null, '', $timespent->timespent_id, 'project_task_time'); + if (isset($task->linkedObjects['dolisirh_timesheet'])) { + $object->element = 'dolisirh_timesheet'; + $object->deleteObjectLinked(null, '', $timespent->timespent_id, 'project_task_time'); + } + } + } + } + + /** + * Overloading the printFieldListOption function : replacing the parent's function with the one below + * + * @param array $parameters Hook metadata (context, etc...) + */ + public function printFieldListOption(array $parameters) { + if ($parameters['currentcontext'] == 'projecttasktime') { + global $langs; + + $parameters['arrayfields']['fk_timesheet'] = array( + 'label' => $langs->trans('TimeSheet'), + 'checked' => 1, + 'enabled' => 1 + ); + + if (!empty($parameters['arrayfields']['fk_timesheet']['checked'])) { + print ''; + } + } + } + + /** + * Overloading the printFieldListTitle function : replacing the parent's function with the one below + * + * @param array $parameters Hook metadata (context, etc...) + */ + public function printFieldListTitle(array $parameters) { + if ($parameters['currentcontext'] == 'projecttasktime') { + global $langs; + + $parameters['arrayfields']['fk_timesheet'] = array( + 'label' => $langs->trans('TimeSheet'), + 'checked' => 1, + 'enabled' => 1 + ); + + if (!empty($parameters['arrayfields']['fk_timesheet']['checked'])) { + print_liste_field_titre($parameters['arrayfields']['fk_timesheet']['label'], $_SERVER['PHP_SELF'], 'fk_timesheet', '', $parameters['param'], '', $parameters['sortfield'], $parameters['sortorder'], 'center '); + } + } + } + + /** + * Overloading the printFieldListValue function : replacing the parent's function with the one below + * + * @param array $parameters Hook metadata (context, etc...) + */ + public function printFieldListValue(array $parameters) { + if ($parameters['currentcontext'] == 'projecttasktime') { + global $langs; + + require_once DOL_DOCUMENT_ROOT . '/projet/class/task.class.php'; + + $task = new Task($this->db); + + $parameters['arrayfields']['fk_timesheet'] = array( + 'label' => $langs->trans('TimeSheet'), + 'checked' => 1, + 'enabled' => 1 + ); + + if (!empty($parameters['arrayfields']['fk_timesheet']['checked'])) { + print ''; + $task->fetchObjectLinked(null, '', $parameters['obj']->rowid, 'project_task_time'); + if (isset($task->linkedObjects['dolisirh_timesheet'])) { + $timesheet = (reset($task->linkedObjects['dolisirh_timesheet'])); + print $timesheet->getNomUrl(1); + } + print ''; + } + } + } +} diff --git a/class/dolisirhsignature.class.php b/class/dolisirhsignature.class.php new file mode 100644 index 0000000..33e83f5 --- /dev/null +++ b/class/dolisirhsignature.class.php @@ -0,0 +1,614 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file class/dolisirhsignature.class.php + * \ingroup dolisirh + * \brief This file is a CRUD class file for DoliSIRHSignature (Create/Read/Update/Delete) + */ + +require_once DOL_DOCUMENT_ROOT . '/core/class/commonobject.class.php'; +require_once DOL_DOCUMENT_ROOT . '/core/lib/ticket.lib.php'; + +/** + * Class for DoliSIRHSignature + */ +class DoliSIRHSignature extends CommonObject +{ + /** + * @var DoliDB Database handler. + */ + public $db; + + /** + * @var string[] Array of error strings + */ + public $errors = array(); + + /** + * @var string ID of module. + */ + public $module = 'dolisirh'; + + /** + * @var string ID to identify managed object. + */ + public $element = 'object_signature'; + + /** + * @var string Name of table without prefix where object is stored. This is also the key used for extrafields management. + */ + public $table_element = 'dolisirh_object_signature'; + + /** + * @var int Does this object support multicompany module ? + * 0=No test on entity, 1=Test with field entity, 'field@table'=Test with link by field@table + */ + public $ismultientitymanaged = 1; + + /** + * @var int Does object support extrafields ? 0=No, 1=Yes + */ + public $isextrafieldmanaged = 0; + + /** + * @var string String with name of icon for dolisirhsignature. Must be the part after the 'object_' into object_dolisirhsignature.png + */ + public $picto = 'object_signature@dolisirh'; + + /** + * @var array Label status of const. + */ + public $labelStatus; + + /** + * @var array Label status short of const. + */ + public $labelStatusShort; + + const STATUS_DELETED = 0; + const STATUS_REGISTERED = 1; + const STATUS_SIGNATURE_REQUEST = 2; + const STATUS_PENDING_SIGNATURE = 3; + const STATUS_DENIED = 4; + const STATUS_SIGNED = 5; + const STATUS_UNSIGNED = 6; + const STATUS_ABSENT = 7; + const STATUS_JUSTIFIED_ABSENT = 8; + + /** + * @var array Array with all fields and their property. Do not use it as a static var. It may be modified by constructor. + */ + public $fields = array( + 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => '1', 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => '1', 'index' => 1, 'comment' => "Id"), + 'entity' => array('type' => 'integer', 'label' => 'Entity', 'enabled' => '1', 'position' => 10, 'notnull' => 1, 'visible' => -1,), + 'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => '1', 'position' => 20, 'notnull' => 1, 'visible' => -2,), + 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => '1', 'position' => 30, 'notnull' => 0, 'visible' => -2,), + 'import_key' => array('type' => 'integer', 'label' => 'ImportId', 'enabled' => '1', 'position' => 40, 'notnull' => 1, 'visible' => -2,), + 'status' => array('type' => 'smallint', 'label' => 'Status', 'enabled' => '1', 'position' => 50, 'notnull' => 0, 'visible' => 1, 'index' => 1,), + 'role' => array('type' => 'varchar(255)', 'label' => 'Role', 'enabled' => '1', 'position' => 60, 'notnull' => 0, 'visible' => 3,), + 'firstname' => array('type' => 'varchar(255)', 'label' => 'Firstname', 'enabled' => '1', 'position' => 70, 'notnull' => 0, 'visible' => 3,), + 'lastname' => array('type' => 'varchar(255)', 'label' => 'Lastname', 'enabled' => '1', 'position' => 80, 'notnull' => 0, 'visible' => 3,), + 'email' => array('type' => 'varchar(255)', 'label' => 'Email', 'enabled' => '1', 'position' => 90, 'notnull' => 0, 'visible' => 3,), + 'phone' => array('type' => 'varchar(255)', 'label' => 'Phone', 'enabled' => '1', 'position' => 100, 'notnull' => 0, 'visible' => 3,), + 'society_name' => array('type' => 'varchar(255)', 'label' => 'SocietyName', 'enabled' => '1', 'position' => 110, 'notnull' => 0, 'visible' => 3,), + 'signature_date' => array('type' => 'datetime', 'label' => 'SignatureDate', 'enabled' => '1', 'position' => 120, 'notnull' => 0, 'visible' => 3,), + 'signature_location' => array('type' => 'varchar(255)', 'label' => 'SignatureLocation', 'enabled' => '1', 'position' => 125, 'notnull' => 0, 'visible' => 3,), + 'signature_comment' => array('type' => 'varchar(255)', 'label' => 'SignatureComment', 'enabled' => '1', 'position' => 130, 'notnull' => 0, 'visible' => 3,), + 'element_id' => array('type' => 'integer', 'label' => 'ElementType', 'enabled' => '1', 'position' => 140, 'notnull' => 1, 'visible' => 1,), + 'element_type' => array('type' => 'varchar(50)', 'label' => 'ElementType', 'enabled' => '1', 'position' => 150, 'notnull' => 0, 'visible' => 1,), + 'signature' => array('type' => 'varchar(255)', 'label' => 'Signature', 'enabled' => '1', 'position' => 160, 'notnull' => 0, 'visible' => 3,), + 'stamp' => array('type' => 'varchar(255)', 'label' => 'Stamp', 'enabled' => '1', 'position' => 165, 'notnull' => 0, 'visible' => 3,), + 'signature_url' => array('type' => 'varchar(50)', 'label' => 'SignatureUrl', 'enabled' => '1', 'position' => 170, 'notnull' => 0, 'visible' => 1, 'default' => null,), + 'transaction_url' => array('type' => 'varchar(50)', 'label' => 'TransactionUrl', 'enabled' => '1', 'position' => 180, 'notnull' => 0, 'visible' => 1,'default' => null,), + 'last_email_sent_date' => array('type' => 'datetime', 'label' => 'LastEmailSentDate', 'enabled' => '1', 'position' => 190, 'notnull' => 0, 'visible' => 3,), + 'object_type' => array('type' => 'varchar(255)', 'label' => 'object_type', 'enabled' => '1', 'position' => 195, 'notnull' => 0, 'visible' => 0,), + 'fk_object' => array('type' => 'integer', 'label' => 'FKObject', 'enabled' => '1', 'position' => 200, 'notnull' => 1, 'visible' => 0,), + ); + + public $rowid; + public $entity; + public $date_creation; + public $tms; + public $import_key; + public $status; + public $role; + public $firstname; + public $lastname; + public $email; + public $phone; + public $society_name; + public $signature_date; + public $element_id; + public $element_type; + public $signature; + public $stamp; + public $signature_url; + public $last_email_sent_date; + public $object_type; + public $fk_object; + + /** + * Constructor + * + * @param DoliDb $db Database handler + */ + public function __construct(DoliDB $db) + { + global $conf, $langs; + + $this->db = $db; + + if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && isset($this->fields['rowid'])) $this->fields['rowid']['visible'] = 0; + if (empty($conf->multicompany->enabled) && isset($this->fields['entity'])) $this->fields['entity']['enabled'] = 0; + + // Unset fields that are disabled + foreach ($this->fields as $key => $val) { + if (isset($val['enabled']) && empty($val['enabled'])) { + unset($this->fields[$key]); + } + } + + // Translate some data of arrayofkeyval + if (is_object($langs)) { + foreach ($this->fields as $key => $val) { + if ( ! empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) { + foreach ($val['arrayofkeyval'] as $key2 => $val2) { + $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2); + } + } + } + } + } + + /** + * Create object into database + * + * @param User $user User that creates + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int 0 < if KO, id of created object if OK + */ + public function create(User $user, bool $notrigger = false): int + { + return $this->createCommon($user, $notrigger); + } + + /** + * Load object in memory from the database + * + * @param int $id ID object + * @param string|null $ref Ref + * @param string $morewhere More SQL filters (' AND ...') + * @return int 0 < if KO, 0 if not found, >0 if OK + */ + public function fetch(int $id, string $ref = null, string $morewhere = ''): int + { + return $this->fetchCommon($id, $ref, $morewhere); + } + + /** + * Load list of objects in memory from the database. + * + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit Limit + * @param int $offset Offset + * @param array $filter Filter array. Example array('field'=>'value', 'customurl'=>...) + * @param string $filtermode Filter mode (AND/OR) + * @param string $old_table_element Old table element due to rework + * @return array|int int <0 if KO, array of pages if OK + * @throws Exception + */ + public function fetchAll(string $sortorder = '', string $sortfield = '', int $limit = 0, int $offset = 0, array $filter = array(), string $filtermode = 'AND', string $old_table_element = '') + { + dol_syslog(__METHOD__, LOG_DEBUG); + + $records = array(); + + $sql = 'SELECT '; + if (dol_strlen($old_table_element) > 0) { + unset($this->fields['signature_location']); + unset($this->fields['object_type']); + } + $sql .= $this->getFieldList(); + + if (dol_strlen($old_table_element)) { + $sql .= ' FROM ' . MAIN_DB_PREFIX . $old_table_element . ' as t'; + } else { + $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t'; + } if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) $sql .= ' WHERE t.entity IN (' . getEntity($this->table_element) . ')'; + else $sql .= ' WHERE 1 = 1'; + // Manage filter + $sqlwhere = array(); + if (count($filter) > 0) { + foreach ($filter as $key => $value) { + if ($key == 't.rowid') { + $sqlwhere[] = $key . '=' . $value; + } elseif (in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { + $sqlwhere[] = $key . ' = \'' . $this->db->idate($value) . '\''; + } elseif ($key == 'customsql') { + $sqlwhere[] = $value; + } elseif (strpos($value, '%') === false) { + $sqlwhere[] = $key . ' IN (' . $this->db->sanitize($this->db->escape($value)) . ')'; + } else { + $sqlwhere[] = $key . ' LIKE \'%' . $this->db->escape($value) . '%\''; + } + } + } + if (count($sqlwhere) > 0) { + $sql .= ' AND (' . implode(' ' . $filtermode . ' ', $sqlwhere) . ')'; + } + + if ( ! empty($sortfield)) { + $sql .= $this->db->order($sortfield, $sortorder); + } + if ( ! empty($limit)) { + $sql .= ' ' . $this->db->plimit($limit, $offset); + } + $resql = $this->db->query($sql); + + if ($resql) { + $num = $this->db->num_rows($resql); + $i = 0; + while ($i < ($limit ? min($limit, $num) : $num)) { + $obj = $this->db->fetch_object($resql); + + $record = new self($this->db); + $record->setVarsFromFetchObj($obj); + + $records[$record->id] = $record; + + $i++; + } + $this->db->free($resql); + + return $records; + } else { + $this->errors[] = 'Error ' . $this->db->lasterror(); + dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR); + + return -1; + } + } + + /** + * Update object into database + * + * @param User $user User that modifies + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int 0 < if KO, >0 if OK + */ + public function update(User $user, bool $notrigger = false): int + { + return $this->updateCommon($user, $notrigger); + } + + /** + * Delete object in database + * + * @param User $user User that deletes + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int 0 < if KO, >0 if OK + */ + public function delete(User $user, bool $notrigger = false): int + { + return $this->deleteCommon($user, $notrigger); + } + + /** + * Set registered status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int 0 < if KO, >0 if OK + */ + public function setRegistered(User $user, int $notrigger = 0): int + { + return $this->setStatusCommon($user, self::STATUS_REGISTERED, $notrigger, 'DOLISIRHSIGNATURE_REGISTERED'); + } + + /** + * Set pending status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int 0 < if KO, >0 if OK + */ + public function setPending(User $user, int $notrigger = 0): int + { + return $this->setStatusCommon($user, self::STATUS_PENDING_SIGNATURE, $notrigger, 'DOLISIRHSIGNATURE_PENDING_SIGNATURE'); + } + + /** + * Set signed status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int 0 < if KO, >0 if OK + */ + public function setSigned(User $user, int $notrigger = 0): int + { + return $this->setStatusCommon($user, self::STATUS_SIGNED, $notrigger, 'DOLISIRHSIGNATURE_SIGNED'); + } + + /** + * Set absent status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int 0 < if KO, >0 if OK + */ + public function setAbsent(User $user, int $notrigger = 0): int + { + return $this->setStatusCommon($user, self::STATUS_ABSENT, $notrigger, 'DOLISIRHSIGNATURE_ABSENT'); + } + + /** + * Set deleted status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int 0 < if KO, >0 if OK + */ + public function setDeleted(User $user, int $notrigger = 0): int + { + return $this->setStatusCommon($user, self::STATUS_DELETED, $notrigger, 'DOLISIRHSIGNATURE_DELETED'); + } + + /** + * Return the label of the status + * + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto + * @return string Label of status + */ + public function getLibStatut(int $mode = 0): string + { + return $this->LibStatut($this->status, $mode); + } + + /** + * Return the status + * + * @param int $status Id status + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto + * @return string Label of status + */ + public function LibStatut(int $status, int $mode = 0): string + { + if (empty($this->labelStatus) || empty($this->labelStatusShort)) { + global $langs; + $this->labelStatus[self::STATUS_DELETED] = $langs->transnoentities('Deleted'); + $this->labelStatus[self::STATUS_REGISTERED] = $langs->transnoentities('Registered'); + $this->labelStatus[self::STATUS_SIGNATURE_REQUEST] = $langs->transnoentities('SignatureRequest'); + $this->labelStatus[self::STATUS_PENDING_SIGNATURE] = $langs->transnoentities('PendingSignature'); + $this->labelStatus[self::STATUS_DENIED] = $langs->transnoentities('Denied'); + $this->labelStatus[self::STATUS_SIGNED] = $langs->transnoentities('Signed'); + $this->labelStatus[self::STATUS_UNSIGNED] = $langs->transnoentities('Unsigned'); + $this->labelStatus[self::STATUS_ABSENT] = $langs->transnoentities('Absent'); + $this->labelStatus[self::STATUS_JUSTIFIED_ABSENT] = $langs->transnoentities('JustifiedAbsent'); + } + + $statusType = 'status' . $status; + if ($status == self::STATUS_SIGNED) $statusType = 'status4'; + if ($status == self::STATUS_ABSENT) $statusType = 'status8'; + + return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode); + } + + /** + * Create signatory in database + * + * @param int $fk_object ID of object linked + * @param string $object_type Type of object + * @param string $element_type Type of resource + * @param array $element_ids ID of resource + * @param string $role Role of resource + * @param int $noupdate Update previous signatories + * @return int + * @throws Exception + */ + public function setSignatory(int $fk_object, string $object_type, string $element_type, array $element_ids, string $role = "", int $noupdate = 0): int + { + global $conf, $user; + + $society = new Societe($this->db); + $result = 0; + if ( ! empty($element_ids) && $element_ids > 0) { + if ( ! $noupdate) { + $this->deletePreviousSignatories($role, $fk_object, $object_type); + } + foreach ($element_ids as $element_id) { + if ($element_id > 0) { + $signatory_data = ''; + if ($element_type == 'user') { + $signatory_data = new User($this->db); + + $signatory_data->fetch($element_id); + + if ($signatory_data->socid > 0) { + $society->fetch($signatory_data->socid); + $this->society_name = $society->name; + } else { + $this->society_name = $conf->global->MAIN_INFO_SOCIETE_NOM; + } + + $this->phone = $signatory_data->user_mobile; + } elseif ($element_type == 'socpeople') { + $signatory_data = new Contact($this->db); + + $signatory_data->fetch($element_id); + if (!is_object($signatory_data)) { + $signatory_data = new StdClass(); + } + + $society->fetch($signatory_data->socid); + + $this->society_name = $society->name; + $this->phone = $signatory_data->phone_mobile; + } + + $this->status = self::STATUS_REGISTERED; + + $this->firstname = $signatory_data->firstname; + $this->lastname = $signatory_data->lastname; + $this->email = $signatory_data->email; + $this->role = $role; + + $this->element_type = $element_type; + $this->element_id = $element_id; + + $this->signature_url = generate_random_id(); + + $this->fk_object = $fk_object; + + $result = $this->create($user); + } + } + } + if ($result > 0 ) { + return 1; + } else { + return 0; + } + } + + /** + * Fetch signatory from database + * + * @param string $role Role of resource + * @param int $fk_object ID of object linked + * @param string $object_type ID of object linked + * @return array|int + * @throws Exception + */ + public function fetchSignatory(string $role, int $fk_object, string $object_type) + { + $filter = array('customsql' => 'fk_object=' . $fk_object . ' AND status!=0 AND object_type="' . $object_type . '"'); + if (strlen($role)) { + $filter['customsql'] .= ' AND role = "' . $role . '"'; + return $this->fetchAll('', '', 0, 0, $filter); + } else { + $signatories = $this->fetchAll('', '', 0, 0, $filter); + if ( ! empty($signatories) && $signatories > 0) { + $signatoriesArray = array(); + foreach ($signatories as $signatory) { + $signatoriesArray[$signatory->role][$signatory->id] = $signatory; + } + return $signatoriesArray; + } else { + return 0; + } + } + } + + /** + * Fetch signatories in database with parent ID + * + * @param int $fk_object ID of object linked + * @param string $object_type Type of object + * @param string $morefilter Filter + * @return array|integer + * @throws Exception + */ + public function fetchSignatories(int $fk_object, string $object_type, string $morefilter = '1 = 1') + { + $filter = array('customsql' => 'fk_object=' . $fk_object . ' AND ' . $morefilter . ' AND object_type="' . $object_type . '"' . ' AND status > 0'); + return $this->fetchAll('', '', 0, 0, $filter); + } + + /** + * Check if signatories signed + * + * @param int $fk_object ID of object linked + * @param string $object_type Type of object + * @return int + * @throws Exception + */ + public function checkSignatoriesSignatures(int $fk_object, string $object_type): int + { + $morefilter = 'status != 0'; + + $signatories = $this->fetchSignatories($fk_object, $object_type, $morefilter); + + if ( ! empty($signatories) && $signatories > 0) { + foreach ($signatories as $signatory) { + if ($signatory->status == 5 || $signatory->status == 7) { + continue; + } else { + return 0; + } + } + return 1; + } else { + return -1; + } + } + + /** + * Delete signatories signatures + * + * @param int $fk_object ID of object linked + * @param string $object_type Type of object + * @return int + * @throws Exception + */ + public function deleteSignatoriesSignatures(int $fk_object, string $object_type): int + { + global $user; + + $signatories = $this->fetchSignatories($fk_object, $object_type); + + if ( ! empty($signatories) && $signatories > 0) { + foreach ($signatories as $signatory) { + if (dol_strlen($signatory->signature)) { + $signatory->signature = ''; + $signatory->signature_date = ''; + $signatory->status = 1; + $signatory->update($user); + } + } + return 1; + } else { + return -1; + } + } + + /** + * Set previous signatories status to 0 + * + * @param string $role Role of resource + * @param int $fk_object ID of object linked + * @param string $object_type Type of object linked + * @return int + * @throws Exception + */ + public function deletePreviousSignatories(string $role, int $fk_object, string $object_type): int + { + global $user; + $filter = array('customsql' => ' role="' . $role . '" AND fk_object=' . $fk_object . ' AND status=1 AND object_type="' . $object_type . '"'); + $signatoriesToDelete = $this->fetchAll('', '', 0, 0, $filter); + + if ( ! empty($signatoriesToDelete) && $signatoriesToDelete > 0) { + foreach ($signatoriesToDelete as $signatoryToDelete) { + $signatoryToDelete->setDeleted($user, true); + } + return 1; + } else { + return -1; + } + } +} diff --git a/class/dolisirhstats.php b/class/dolisirhstats.php new file mode 100644 index 0000000..6f83ec4 --- /dev/null +++ b/class/dolisirhstats.php @@ -0,0 +1,593 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file class/dolisirhstats.class.php + * \ingroup dolisirh + * \brief DoliSIRH class to manage statistics reports + */ + +/** + * Parent class of statistics class + */ +abstract class DoliSIRHStats +{ + /** + * @var DoliDB Database handler. + */ + protected $db; + + /** + * @var array Dates of cache file read by methods. + */ + protected $lastfetchdate = array(); + + /** + * @var string Suffix to add to name of cache file (to avoid file name conflicts) + */ + public $cachefilesuffix = ''; + + /** + * Return nb of elements by month for several years + * + * @param int $endyear End year + * @param int $startyear Start year + * @param int $cachedelay Delay we accept for cache file (0=No read, no save of cache, -1=No read but save) + * @param int $format 0=Label of abscissa is a translated text, 1=Label of abscissa is month number, 2=Label of abscissa is first letter of month + * @param int $startmonth Month of the fiscal year start min 1 max 12 ; if 1 = january + * @return array|int Array of values + * @throws Exception + */ + public function getNbByMonthWithPrevYear(int $endyear, int $startyear, int $cachedelay = 0, int $format = 0, int $startmonth = 1) + { + global $conf, $user, $langs; + + if ($startyear > $endyear) { + return -1; + } + + $datay = array(); + + // Search into cache + if (!empty($cachedelay)) { + include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + include_once DOL_DOCUMENT_ROOT.'/core/lib/json.lib.php'; + } + + $newpathofdestfile = $conf->user->dir_temp.'/'.get_class($this).'_'.__FUNCTION__.'_'.(empty($this->cachefilesuffix) ? '' : $this->cachefilesuffix.'_').$langs->defaultlang.'_entity.'.$conf->entity.'_user'.$user->id.'.cache'; + $newmask = '0644'; + + $nowgmt = dol_now(); + + $foundintocache = 0; + if ($cachedelay > 0) { + $filedate = dol_filemtime($newpathofdestfile); + if ($filedate >= ($nowgmt - $cachedelay)) { + $foundintocache = 1; + + $this->lastfetchdate[get_class($this).'_'.__FUNCTION__] = $filedate; + } else { + dol_syslog(get_class($this).'::'.__FUNCTION__." cache file ".$newpathofdestfile." is not found or older than now - cachedelay (".$nowgmt." - ".$cachedelay.") so we can't use it."); + } + } + // Load file into $data + if ($foundintocache) { // Cache file found and is not too old + if (!empty($filedate)) { + dol_syslog(get_class($this).'::'.__FUNCTION__." read data from cache file ".$newpathofdestfile." ".$filedate."."); + } + $data = json_decode(file_get_contents($newpathofdestfile), true); + } else { + $year = $startyear; + $sm = $startmonth - 1; + if ($sm != 0) { + $year = $year - 1; + } + while ($year <= $endyear) { + $datay[$year] = $this->getNbByMonth($year, $format); + $year++; + } + + $data = array(); + + for ($i = 0; $i < 12; $i++) { + $data[$i][] = $datay[$endyear][($i + $sm) % 12][0]; + $year = $startyear; + while ($year <= $endyear) { + $data[$i][] = $datay[$year][($i + $sm) % 12][1]; + $year++; + } + } + + } + + // Save cache file + if (empty($foundintocache) && ($cachedelay > 0 || $cachedelay == -1)) { + dol_syslog(get_class($this).'::'.__FUNCTION__." save cache file ".$newpathofdestfile." onto disk."); + if (!dol_is_dir($conf->user->dir_temp)) { + dol_mkdir($conf->user->dir_temp); + } + $fp = fopen($newpathofdestfile, 'w'); + fwrite($fp, json_encode($data)); + fclose($fp); + if (!empty($conf->global->MAIN_UMASK)) { + $newmask = $conf->global->MAIN_UMASK; + } + @chmod($newpathofdestfile, octdec($newmask)); + + $this->lastfetchdate[get_class($this).'_'.__FUNCTION__] = $nowgmt; + } + + // return array(array('Month',val1,val2,val3),...) + return $data; + } + + /** + * Return amount of elements by month for several years. + * + * @param int $endyear End year + * @param int $startyear Start year + * @param int $cachedelay Delay we accept for cache file (0=No read, no save of cache, -1=No read but save) + * @param int $format 0=Label of abscissa is a translated text, 1=Label of abscissa is month number, 2=Label of abscissa is first letter of month + * @param int $startmonth Month of the fiscal year start min 1 max 12 ; if 1 = january + * @return array|int Array of values + * @throws Exception + */ + public function getAmountByMonthWithPrevYear(int $endyear, int $startyear, int $cachedelay = 0, int $format = 0, int $startmonth = 1) + { + global $conf, $user, $langs; + + if ($startyear > $endyear) { + return -1; + } + + $datay = array(); + + // Search into cache + if (!empty($cachedelay)) { + include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + include_once DOL_DOCUMENT_ROOT.'/core/lib/json.lib.php'; + } + + $newpathofdestfile = $conf->user->dir_temp.'/'.get_class($this).'_'.__FUNCTION__.'_'.(empty($this->cachefilesuffix) ? '' : $this->cachefilesuffix.'_').$langs->defaultlang.'_entity.'.$conf->entity.'_user'.$user->id.'.cache'; + $newmask = '0644'; + + $nowgmt = dol_now(); + + $foundintocache = 0; + if ($cachedelay > 0) { + $filedate = dol_filemtime($newpathofdestfile); + if ($filedate >= ($nowgmt - $cachedelay)) { + $foundintocache = 1; + + $this->lastfetchdate[get_class($this).'_'.__FUNCTION__] = $filedate; + } else { + dol_syslog(get_class($this).'::'.__FUNCTION__." cache file ".$newpathofdestfile." is not found or older than now - cachedelay (".$nowgmt." - ".$cachedelay.") so we can't use it."); + } + } + + // Load file into $data + if ($foundintocache) { // Cache file found and is not too old + if (!empty($filedate)) { + dol_syslog(get_class($this).'::'.__FUNCTION__." read data from cache file ".$newpathofdestfile." ".$filedate."."); + } + $data = json_decode(file_get_contents($newpathofdestfile), true); + } else { + $year = $startyear; + $sm = $startmonth - 1; + if ($sm != 0) { + $year = $year - 1; + } + while ($year <= $endyear) { + $datay[$year] = $this->getAmountByMonth($year, $format); + $year++; + } + + $data = array(); + // $data = array('xval'=>array(0=>xlabel,1=>yval1,2=>yval2...),...) + for ($i = 0; $i < 12; $i++) { + $data[$i][] = $datay[$endyear][($i + $sm) % 12]['label'] ?? $datay[$endyear][($i + $sm) % 12][0]; // set label + $year = $startyear; + while ($year <= $endyear) { + $data[$i][] = $datay[$year][($i + $sm) % 12][1]; // set yval for x=i + $year++; + } + } + } + + // Save cache file + if (empty($foundintocache) && ($cachedelay > 0 || $cachedelay == -1)) { + dol_syslog(get_class($this).'::'.__FUNCTION__." save cache file ".$newpathofdestfile." onto disk."); + if (!dol_is_dir($conf->user->dir_temp)) { + dol_mkdir($conf->user->dir_temp); + } + $fp = fopen($newpathofdestfile, 'w'); + if ($fp) { + fwrite($fp, json_encode($data)); + fclose($fp); + if (!empty($conf->global->MAIN_UMASK)) { + $newmask = $conf->global->MAIN_UMASK; + } + @chmod($newpathofdestfile, octdec($newmask)); + } else { + dol_syslog("Failed to write cache file", LOG_ERR); + } + $this->lastfetchdate[get_class($this).'_'.__FUNCTION__] = $nowgmt; + } + + return $data; + } + + /** + * Return average of entity by month for several years + * + * @param int $endyear End year + * @param int $startyear Start year + * @param int $cachedelay Delay we accept for cache file (0=No read, no save of cache, -1=No read but save) + * @param int $format 0=Label of abscissa is a translated text, 1=Label of abscissa is month number, 2=Label of abscissa is first letter of month + * @param int $startmonth Month of the fiscal year start min 1 max 12 ; if 1 = january + * @return array|int Array of values + * @throws Exception + */ + public function getAverageByMonthWithPrevYear(int $endyear, int $startyear, int $cachedelay = 0, int $format = 0, int $startmonth = 1) + { + global $conf, $user, $langs; + + if ($startyear > $endyear) { + return -1; + } + + $datay = array(); + + // Search into cache + if (!empty($cachedelay)) { + include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + include_once DOL_DOCUMENT_ROOT.'/core/lib/json.lib.php'; + } + + $newpathofdestfile = $conf->user->dir_temp.'/'.get_class($this).'_'.__FUNCTION__.'_'.(empty($this->cachefilesuffix) ? '' : $this->cachefilesuffix.'_').$langs->defaultlang.'_entity.'.$conf->entity.'_user'.$user->id.'.cache'; + $newmask = '0644'; + + $nowgmt = dol_now(); + + $foundintocache = 0; + if ($cachedelay > 0) { + $filedate = dol_filemtime($newpathofdestfile); + if ($filedate >= ($nowgmt - $cachedelay)) { + $foundintocache = 1; + + $this->lastfetchdate[get_class($this).'_'.__FUNCTION__] = $filedate; + } else { + dol_syslog(get_class($this).'::'.__FUNCTION__." cache file ".$newpathofdestfile." is not found or older than now - cachedelay (".$nowgmt." - ".$cachedelay.") so we can't use it."); + } + } + + // Load file into $data + if ($foundintocache) { // Cache file found and is not too old + if (!empty($filedate)) { + dol_syslog(get_class($this).'::'.__FUNCTION__." read data from cache file ".$newpathofdestfile." ".$filedate."."); + } + $data = json_decode(file_get_contents($newpathofdestfile), true); + } else { + $year = $startyear; + $sm = $startmonth - 1; + if ($sm != 0) { + $year = $year - 1; + } + while ($year <= $endyear) { + $datay[$year] = $this->getAverageByMonth($year, $format); + $year++; + } + + $data = array(); + + for ($i = 0; $i < 12; $i++) { + $data[$i][] = $datay[$endyear][($i + $sm) % 12][0]; + $year = $startyear; + while ($year <= $endyear) { + $data[$i][] = $datay[$year][($i + $sm) % 12][1]; + $year++; + } + } + } + + // Save cache file + if (empty($foundintocache) && ($cachedelay > 0 || $cachedelay == -1)) { + dol_syslog(get_class($this).'::'.__FUNCTION__." save cache file ".$newpathofdestfile." onto disk."); + if (!dol_is_dir($conf->user->dir_temp)) { + dol_mkdir($conf->user->dir_temp); + } + $fp = fopen($newpathofdestfile, 'w'); + if ($fp) { + fwrite($fp, json_encode($data)); + fclose($fp); + if (!empty($conf->global->MAIN_UMASK)) { + $newmask = $conf->global->MAIN_UMASK; + } + @chmod($newpathofdestfile, octdec($newmask)); + } else { + dol_syslog("Failed to write cache file", LOG_ERR); + } + $this->lastfetchdate[get_class($this).'_'.__FUNCTION__] = $nowgmt; + } + + return $data; + } + + /** + * Return nb of elements by year + * + * @param string $sql SQL request + * @return array + * @throws Exception + */ + protected function _getNbByYear(string $sql): array + { + // phpcs:enable + $result = array(); + + dol_syslog(get_class($this).'::'.__FUNCTION__, LOG_DEBUG); + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + $i = 0; + while ($i < $num) { + $row = $this->db->fetch_row($resql); + $result[$i] = $row; + $i++; + } + $this->db->free($resql); + } else { + dol_print_error($this->db); + } + return $result; + } + + /** + * Return nb of elements, total amount and avg amount each year + * + * @param string $sql SQL request + * @return array Array with nb, total amount, average for each year + * @throws Exception + */ + protected function _getAllByYear(string $sql): array + { + // phpcs:enable + $result = array(); + + dol_syslog(get_class($this).'::'.__FUNCTION__, LOG_DEBUG); + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + $i = 0; + while ($i < $num) { + $row = $this->db->fetch_object($resql); + $result[$i]['year'] = $row->year; + $result[$i]['nb'] = $row->nb; + if ($i > 0 && $row->nb > 0) { + $result[$i - 1]['nb_diff'] = ($result[$i - 1]['nb'] - $row->nb) / $row->nb * 100; + } + $result[$i]['total'] = $row->total; + if ($i > 0 && $row->total > 0) { + $result[$i - 1]['total_diff'] = ($result[$i - 1]['total'] - $row->total) / $row->total * 100; + } + $result[$i]['avg'] = $row->avg; + if ($i > 0 && $row->avg > 0) { + $result[$i - 1]['avg_diff'] = ($result[$i - 1]['avg'] - $row->avg) / $row->avg * 100; + } + // For some $sql only + if (isset($row->weighted)) { + $result[$i]['weighted'] = $row->weighted; + if ($i > 0 && $row->weighted > 0) { + $result[$i - 1]['avg_weighted'] = ($result[$i - 1]['weighted'] - $row->weighted) / $row->weighted * 100; + } + } + $i++; + } + $this->db->free($resql); + } else { + dol_print_error($this->db); + } + return $result; + } + + /** + * Return number of elements per month for a given year + * + * @param string $sql SQL + * @param int $format 0=Label of abscissa is a translated text, 1=Label of abscissa is month number, 2=Label of abscissa is first letter of month + * @return array Array of nb each month + * @throws Exception + */ + protected function _getNbByMonth(string $sql, int $format = 0): array + { + // phpcs:enable + global $langs; + + $result = array(); + $res = array(); + + dol_syslog(get_class($this).'::'.__FUNCTION__, LOG_DEBUG); + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + $i = 0; + while ($i < $num) { + $row = $this->db->fetch_row($resql); + $j = $row[0] * 1; + $result[$j] = $row[1]; + $i++; + } + $this->db->free($resql); + } else { + dol_print_error($this->db); + } + + for ($i = 1; $i < 13; $i++) { + $res[$i] = ($result[$i] ?? 0); + } + + $data = array(); + + for ($i = 1; $i < 13; $i++) { + $month = 'unknown'; + if ($format == 0) { + $month = $langs->transnoentitiesnoconv('MonthShort'.sprintf("%02d", $i)); + } elseif ($format == 1) { + $month = $i; + } elseif ($format == 2) { + $month = $langs->transnoentitiesnoconv('MonthVeryShort'.sprintf("%02d", $i)); + } + $data[$i - 1] = array($month, $res[$i]); + } + + return $data; + } + + /** + * Return the amount per month for a given year + * + * @param string $sql SQL + * @param int $format 0=Label of abscissa is a translated text, 1=Label of abscissa is month number, 2=Label of abscissa is first letter of month + * @return array Array of amount each month + * @throws Exception + */ + protected function _getAmountByMonth(string $sql, int $format = 0): array + { + // phpcs:enable + global $langs; + + $result = array(); + $res = array(); + + dol_syslog(get_class($this).'::'.__FUNCTION__, LOG_DEBUG); + + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + $i = 0; + while ($i < $num) { + $row = $this->db->fetch_row($resql); + $j = $row[0] * 1; + $result[$j] = $row[1]; + $i++; + } + $this->db->free($resql); + } else { + dol_print_error($this->db); + } + + for ($i = 1; $i < 13; $i++) { + $res[$i] = (int) round(($result[$i] ?? 0)); + } + + $data = array(); + + for ($i = 1; $i < 13; $i++) { + $month = 'unknown'; + if ($format == 0) { + $month = $langs->transnoentitiesnoconv('MonthShort'.sprintf("%02d", $i)); + } elseif ($format == 1) { + $month = $i; + } elseif ($format == 2) { + $month = $langs->transnoentitiesnoconv('MonthVeryShort'.sprintf("%02d", $i)); + } + $data[$i - 1] = array($month, $res[$i]); + } + + return $data; + } + + /** + * Return the amount average par month for a given year + * + * @param string $sql SQL + * @param int $format 0=Label of abscissa is a translated text, 1=Label of abscissa is month number, 2=Label of abscissa is first letter of month + * @return array + * @throws Exception + */ + protected function _getAverageByMonth(string $sql, int $format = 0): array + { + // phpcs:enable + global $langs; + + $result = array(); + $res = array(); + + dol_syslog(get_class($this).'::'.__FUNCTION__, LOG_DEBUG); + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + $i = 0; + while ($i < $num) { + $row = $this->db->fetch_row($resql); + $j = $row[0] * 1; + $result[$j] = $row[1]; + $i++; + } + $this->db->free($resql); + } else { + dol_print_error($this->db); + } + + for ($i = 1; $i < 13; $i++) { + $res[$i] = ($result[$i] ?? 0); + } + + $data = array(); + + for ($i = 1; $i < 13; $i++) { + $month = 'unknown'; + if ($format == 0) { + $month = $langs->transnoentitiesnoconv('MonthShort'.sprintf("%02d", $i)); + } elseif ($format == 1) { + $month = $i; + } elseif ($format == 2) { + $month = $langs->transnoentitiesnoconv('MonthVeryShort'.sprintf("%02d", $i)); + } + $data[$i - 1] = array($month, $res[$i]); + } + + return $data; + } + + /** + * Returns the summed amounts per year for a given number of past years ending now + * + * @param string $sql SQL + * @return array + */ + protected function _getAmountByYear(string $sql): array + { + $result = array(); + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + $i = 0; + while ($i < $num) { + $row = $this->db->fetch_row($resql); + $result[] = [ + 0 => (int) $row[0], + 1 => (int) $row[1], + ]; + $i++; + } + $this->db->free($resql); + } + return $result; + } +} + diff --git a/class/facturerecstats.class.php b/class/facturerecstats.class.php new file mode 100644 index 0000000..2eda597 --- /dev/null +++ b/class/facturerecstats.class.php @@ -0,0 +1,309 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file class/facturerecstats.class.php + * \ingroup dolisirh + * \brief Recurring invoice class to manage statistics reports + */ +include_once DOL_DOCUMENT_ROOT.'/custom/dolisirh/class/dolisirhstats.php'; +include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture-rec.class.php'; +//include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php'; +include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; + +/** + * Class to manage stats for recurring invoices (customer and supplier) + */ +class FactureRecStats extends DoliSIRHStats +{ + /** + * @var int ID soc + */ + public $socid; + + /** + * @var int ID user + */ + public $userid; + + /** + * @var string Name of table without prefix where object is stored + */ + public $table_element; + + /** + * @var string Suffix to add to name of cache file (to avoid file name conflicts) + */ + public $cachefilesuffix = ''; + + /** + * @var string SQL from + */ + public $from; + + /** + * @var string SQL field + */ + public $field; + + /** + * @var string SQL where + */ + public $where; + + /** + * @var string SQL join + */ + public $join; + + /** + * @var string SQL from line + */ + public $from_line; + + /** + * @var string SQL field line + */ + public $field_line; + + /** + * Constructor + * + * @param DoliDB $db Database handler + * @param int $socid ID third party for filter. This value must be forced during the new to external user company if user is an external user. + * @param string $mode Option ('customer', 'supplier') + * @param int $userid ID user for filter (creation user) + * @param int $typentid ID typent of thirdparty for filter + * @param int $categid ID category of thirdparty for filter + * @param int $categinvoicerecid ID category of Invoice rec for filter + */ + public function __construct(DoliDB $db, int $socid, string $mode, int $userid = 0, int $typentid = 0, int $categid = 0, int $categinvoicerecid = 0) + { + global $user; + + $this->db = $db; + $this->socid = ($socid > 0 ?: 0); + $this->userid = $userid; + $this->cachefilesuffix = $mode; + $this->join = ''; + + if ($mode == 'customer') { + $object = new FactureRec($this->db); + $this->from = MAIN_DB_PREFIX.$object->table_element." as fr"; + $this->from_line = MAIN_DB_PREFIX.$object->table_element_line." as tl"; + $this->field = 'total_ht'; + $this->field_line = 'total_ht'; + } +// if ($mode == 'supplier') { +// $object = new FactureFournisseur($this->db); +// $this->from = MAIN_DB_PREFIX.$object->table_element." as f"; +// $this->from_line = MAIN_DB_PREFIX.$object->table_element_line." as tl"; +// $this->field = 'total_ht'; +// $this->field_line = 'total_ht'; +// } + + $this->where = " fr.suspended >= 0"; + $this->where .= " AND fr.entity IN (".getEntity('invoicerec').")"; + if (empty($user->rights->societe->client->voir) && !$this->socid) { + $this->where .= " AND fr.fk_soc = sc.fk_soc AND sc.fk_user = ".((int) $user->id); + } +// if ($mode == 'customer') { +// $this->where .= " AND (fr.suspended <> 3 OR fr.close_code <> 'replaced')"; // Exclude replaced invoices as they are duplicated (we count closed invoices for other reasons) +// } + if ($this->socid) { + $this->where .= " AND fr.fk_soc = ".((int) $this->socid); + } + if ($this->userid > 0) { + $this->where .= ' AND fr.fk_user_author = '.($this->userid); + } +// if (!empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) { +// $this->where .= " AND f.type IN (0,1,2,5)"; +// } else { +// $this->where .= " AND f.type IN (0,1,2,3,5)"; +// } + + if ($typentid) { + $this->join .= ' LEFT JOIN '.MAIN_DB_PREFIX.'societe as s ON s.rowid = fr.fk_soc'; + $this->where .= ' AND s.fk_typent = '.($typentid); + } + + if ($categid) { + $this->join .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_societe as cs ON cs.fk_soc = fr.fk_soc'; + $this->join .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie as c ON c.rowid = cs.fk_categorie'; + $this->where .= ' AND c.rowid = '.($categid); + } + + if ($categinvoicerecid) { + $this->join .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_invoicerec as cir ON cir.fk_invoicerec = fr.rowid'; + $this->join .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie as c ON c.rowid = cir.fk_categorie'; + $this->where .= ' AND c.rowid = '.($categinvoicerecid); + } + } + + /** + * Return recurring invoices number by month for a year + * + * @param int $year Year to scan + * @param int $format 0=Label of abscissa is a translated text, 1=Label of abscissa is month number, 2=Label of abscissa is first letter of month + * @return array Array of values + * @throws Exception + */ + public function getNbByMonth(int $year, int $format = 0): array + { + global $user; + + $sql = "SELECT date_format(fr.date_when,'%m') as dm, COUNT(*) as nb"; + $sql .= " FROM ".$this->from; + if (empty($user->rights->societe->client->voir) && !$this->socid) { + $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + } + $sql .= $this->join; + $sql .= " WHERE fr.date_when BETWEEN '".$this->db->idate(dol_get_first_day($year))."' AND '".$this->db->idate(dol_get_last_day($year))."'"; + $sql .= " AND ".$this->where; + $sql .= " GROUP BY dm"; + $sql .= $this->db->order('dm', 'DESC'); + + return $this->_getNbByMonth($sql, $format); + } + + + /** + * Return recurring invoices number per year + * + * @return array Array with number by year + * @throws Exception + */ + public function getNbByYear(): array + { + global $user; + + $sql = "SELECT date_format(fr.date_when,'%Y') as dm, COUNT(*), SUM(c.".$this->field.")"; + $sql .= " FROM ".$this->from; + if (empty($user->rights->societe->client->voir) && !$this->socid) { + $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + } + $sql .= $this->join; + $sql .= " WHERE ".$this->where; + $sql .= " GROUP BY dm"; + $sql .= $this->db->order('dm', 'DESC'); + + return $this->_getNbByYear($sql); + } + + + /** + * Return the recurring invoices amount by month for a year + * + * @param int $year Year to scan + * @param int $format 0=Label of abscissa is a translated text, 1=Label of abscissa is month number, 2=Label of abscissa is first letter of month + * @return array Array with amount by month + * @throws Exception + */ + public function getAmountByMonth(int $year, int $format = 0): array + { + global $user; + + $sql = "SELECT date_format(date_when,'%m') as dm, SUM(fr.".$this->field.")"; + $sql .= " FROM ".$this->from; + if (empty($user->rights->societe->client->voir) && !$this->socid) { + $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + } + $sql .= $this->join; + $sql .= " WHERE fr.date_when BETWEEN '".$this->db->idate(dol_get_first_day($year))."' AND '".$this->db->idate(dol_get_last_day($year))."'"; + $sql .= " AND ".$this->where; + $sql .= " GROUP BY dm"; + $sql .= $this->db->order('dm', 'DESC'); + + return $this->_getAmountByMonth($sql, $format); + } + + /** + * Return average amount + * + * @param int $year Year to scan + * @param int $format 0=Label of abscissa is a translated text, 1=Label of abscissa is month number, 2=Label of abscissa is first letter of month + * @return array Array of values + * @throws Exception + */ + public function getAverageByMonth(int $year, int $format = 0): array + { + global $user; + + $sql = "SELECT date_format(date_when,'%m') as dm, AVG(fr.".$this->field.")"; + $sql .= " FROM ".$this->from; + if (empty($user->rights->societe->client->voir) && !$this->socid) { + $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + } + $sql .= $this->join; + $sql .= " WHERE fr.date_when BETWEEN '".$this->db->idate(dol_get_first_day($year))."' AND '".$this->db->idate(dol_get_last_day($year))."'"; + $sql .= " AND ".$this->where; + $sql .= " GROUP BY dm"; + $sql .= $this->db->order('dm', 'DESC'); + + return $this->_getAverageByMonth($sql, $format); + } + + /** + * Return nb, total and average + * + * @return array Array of values + * @throws Exception + */ + public function getAllByYear(): array + { + global $user; + + $sql = "SELECT date_format(date_when,'%Y') as year, COUNT(*) as nb, SUM(fr.".$this->field.") as total, AVG(fr.".$this->field.") as avg"; + $sql .= " FROM ".$this->from; + if (empty($user->rights->societe->client->voir) && !$this->socid) { + $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + } + $sql .= $this->join; + $sql .= " WHERE ".$this->where; + $sql .= " GROUP BY year"; + $sql .= $this->db->order('year', 'DESC'); + + return $this->_getAllByYear($sql); + } + + /** + * Return the recurring invoices amount by year for a number of past years + * + * @param int $numberYears Years to scan + * @return array Array with amount by year + */ + public function getAmountByYear(int $numberYears): array + { + global $user; + + $endYear = date('Y'); + $startYear = $endYear - $numberYears; + $sql = "SELECT date_format(date_when,'%Y') as dm, SUM(fr.".$this->field.")"; + $sql .= " FROM ".$this->from; + if (empty($user->rights->societe->client->voir) && !$this->socid) { + $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + } + $sql .= $this->join; + $sql .= " WHERE fr.date_when BETWEEN '".$this->db->idate(dol_get_first_day($startYear))."' AND '".$this->db->idate(dol_get_last_day($endYear))."'"; + $sql .= " AND ".$this->where; + $sql .= " GROUP BY dm"; + $sql .= $this->db->order('dm', 'ASC'); + + return $this->_getAmountByYear($sql); + } +} + diff --git a/class/index.php b/class/index.php new file mode 100644 index 0000000..17927e6 --- /dev/null +++ b/class/index.php @@ -0,0 +1,2 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file class/timesheet.class.php + * \ingroup dolisirh + * \brief This file is a CRUD class file for TimeSheet (Create/Read/Update/Delete) + */ + +require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/functions.lib.php'; + +require_once __DIR__ . '/dolisirhsignature.class.php'; + +/** + * Class for TimeSheet + */ +class TimeSheet extends CommonObject +{ + /** + * @var string ID of module. + */ + public $module = 'dolisirh'; + + /** + * @var string ID to identify managed object. + */ + public $element = 'timesheet'; + + /** + * @var string Name of table without prefix where object is stored. This is also the key used for extrafields management. + */ + public $table_element = 'dolisirh_timesheet'; + + /** + * @var int Does this object support multicompany module ? + * 0=No test on entity, 1=Test with field entity, 'field@table'=Test with link by field@table + */ + public $ismultientitymanaged = 1; + + /** + * @var int Does object support extrafields ? 0=No, 1=Yes + */ + public $isextrafieldmanaged = 1; + + /** + * @var string String with name of icon for timesheet. Must be the part after the 'object_' into object_timesheet.png + */ + public $picto = 'timesheet@dolisirh'; + + /** + * @var array Label status of const. + */ + public $labelStatus; + + /** + * @var array Label status short of const. + */ + public $labelStatusShort; + + const STATUS_DRAFT = 0; + const STATUS_VALIDATED = 1; + const STATUS_LOCKED = 2; + const STATUS_ARCHIVED = 3; + + /** + * 'type' field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]', 'sellist:TableName:LabelFieldName[:KeyFieldName[:KeyFieldParent[:Filter[:Sortfield]]]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'text:none', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password') + * Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)" + * 'label' the translation key. + * 'picto' is code of a picto to show before value in forms + * 'enabled' is a condition when the field must be managed (Example: 1 or '$conf->global->MY_SETUP_PARAM) + * 'position' is the sort order of field. + * 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0). + * 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing) + * 'noteditable' says if field is not editable (1 or 0) + * 'default' is a default value for creation (can still be overwroted by the Setup of Default Values if field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created. + * 'index' if we want an index in database. + * 'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommanded to name the field fk_...). + * 'searchall' is 1 if we want to search in this field when making a search from the quick search button. + * 'isameasure' must be set to 1 or 2 if field can be used for measure. Field type must be summable like integer or double(24,8). Use 1 in most cases, or 2 if you don't want to see the column total into list (for example for percentage) + * 'css' and 'cssview' and 'csslist' is the CSS style to use on field. 'css' is used in creation and update. 'cssview' is used in view mode. 'csslist' is used for columns in lists. For example: 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'cssview'=>'wordbreak', 'csslist'=>'tdoverflowmax200' + * 'help' is a 'TranslationString' to use to show a tooltip on field. You can also use 'TranslationString:keyfortooltiponlick' for a tooltip on click. + * 'showoncombobox' if value of the field must be visible into the label of the combobox that list record + * 'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code. + * 'arrayofkeyval' to set a list of values if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel"). Note that type can be 'integer' or 'varchar' + * 'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1. + * 'comment' is not used. You can store here any text of your choice. It is not used by application. + * 'validate' is 1 if you need to validate with $this->validateField() + * 'copytoclipboard' is 1 or 2 to allow to add a picto to copy value into clipboard (1=picto after label, 2=picto after value) + * + * Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor. + */ + + /** + * @var array Array with all fields and their property. Do not use it as a static var. It may be modified by constructor. + */ + public $fields = array( + 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>0, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'comment'=>"Id"), + 'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>'1', 'position'=>10, 'notnull'=>1, 'visible'=>4, 'noteditable'=>'1', 'default'=>'(PROV)', 'index'=>1, 'searchall'=>1, 'showoncombobox'=>'1', 'validate'=>'1', 'comment'=>"Reference of object"), + 'ref_ext' => array('type'=>'varchar(128)', 'label'=>'RefExt', 'enabled'=>'1', 'position'=>20, 'notnull'=>0, 'visible'=>0,), + 'entity' => array('type'=>'integer', 'label'=>'Entity', 'enabled'=>'1', 'position'=>30,'notnull'=>1, 'visible'=>0,), + 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>'1', 'position'=>40, 'notnull'=>1, 'visible'=>0,), + 'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>'1', 'position'=>50, 'notnull'=>0, 'visible'=>0,), + 'import_key' => array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>'1', 'position'=>60, 'notnull'=>-1, 'visible'=>0,), + 'status' => array('type'=>'integer', 'label'=>'Status', 'enabled'=>'1', 'position'=>70, 'notnull'=>1, 'visible'=>2, 'arrayofkeyval'=>array('0'=>'Draft', '1'=>'Validate', '2'=>'Locked', '3'=>'Archived'),), + 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>'1', 'position'=>80, 'notnull'=>0, 'visible'=>1, 'searchall'=>1, 'css'=>'maxwidth500 widthcentpercentminusxx', 'cssview'=>'wordbreak', 'help'=>"Help text", 'showoncombobox'=>'2',), + 'date_start' => array('type'=>'date', 'label'=>'DateStart', 'enabled'=>'1', 'position'=>90, 'notnull'=>1, 'visible'=>1,), + 'date_end' => array('type'=>'date', 'label'=>'DateEnd', 'enabled'=>'1', 'position'=>100, 'notnull'=>1, 'visible'=>1,), + 'description' => array('type'=>'html', 'label'=>'Description', 'enabled'=>'1', 'position'=>110, 'notnull'=>0, 'visible'=>3,), + 'note_public' => array('type'=>'html', 'label'=>'NotePublic', 'enabled'=>'1', 'position'=>120, 'notnull'=>0, 'visible'=>0,), + 'note_private' => array('type'=>'html', 'label'=>'NotePrivate', 'enabled'=>'1', 'position'=>130, 'notnull'=>0, 'visible'=>0,), + 'last_main_doc' => array('type'=>'varchar(255)', 'label'=>'LastMainDoc', 'enabled'=>'1', 'position'=>140, 'notnull'=>0, 'visible'=>0,), + 'model_pdf' => array('type'=>'varchar(255)', 'label'=>'ModelPdf', 'enabled'=>'1', 'position'=>150, 'notnull'=>-1, 'visible'=>0,), + 'model_odt' => array('type'=>'varchar(255)', 'label'=>'ModelOdt', 'enabled'=>'1', 'position'=>160, 'notnull'=>-1, 'visible'=>0,), + 'fk_user_creat' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserAuthor', 'enabled'=>'1', 'position'=>170, 'notnull'=>1, 'visible'=>0, 'foreignkey'=>'user.rowid',), + 'fk_user_modif' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserModif', 'enabled'=>'1', 'position'=>180, 'notnull'=>-1, 'visible'=>0,), + 'fk_project' => array('type'=>'integer:Project:projet/class/project.class.php:1', 'label'=>'Project', 'enabled'=>'1', 'position'=>82, 'notnull'=>-1, 'visible'=>3, 'index'=>1, 'css'=>'maxwidth500 widthcentpercentminusxx',), + 'fk_soc' => array('type'=>'integer:Societe:societe/class/societe.class.php:1', 'label'=>'ThirdParty', 'enabled'=>'1', 'position'=>101, 'notnull'=>-1, 'visible'=>3, 'index'=>1, 'css'=>'maxwidth500 widthcentpercentminusxx',), + 'fk_user_assign' => array('type'=>'integer:User:user/class/user.class.php:1:t.fk_soc IS NULL', 'label'=>'UserAssign', 'enabled'=>'1', 'position'=>85, 'notnull'=>1, 'visible'=>1, 'index'=>1, 'css'=>'maxwidth500 widthcentpercentminusxx',), + ); + + public $rowid; + public $ref; + public $ref_ext; + public $entity; + public $date_creation; + public $tms; + public $import_key; + public $status; + public $label; + public $date_start; + public $date_end; + public $description; + public $note_public; + public $note_private; + public $last_main_doc; + public $model_pdf; + public $model_odt; + public $fk_user_creat; + public $fk_user_modif; + public $fk_project; + public $fk_soc; + public $fk_user_assign; + + // If this object has a subtable with lines + + /** + * @var string Name of subtable line + */ + public $table_element_line = 'dolisirh_timesheetdet'; + + /** + * @var string Field with ID of parent key if this object has a parent + */ + public $fk_element = 'fk_timesheet'; + + /** + * @var string Name of subtable class that manage subtable lines + */ + public $class_element_line = 'TimeSheetline'; + + /** + * @var array List of child tables. To test if we can delete object. + */ + protected $childtables = array(); + + /** + * @var array List of child tables. To know object to delete on cascade. + * If name matches @ClassNAme:FilePathClass;ParentFkFieldName it will + * call method deleteByParentField(parentId, ParentFkFieldName) to fetch and delete child object + */ + protected $childtablesoncascade = array('dolisirh_timesheetdet'); + + /** + * @var TimeSheetLine[] Array of subtable lines + */ + public $lines = array(); + + + /** + * Constructor + * + * @param DoliDb $db Database handler + */ + public function __construct(DoliDB $db) + { + global $conf, $langs; + + $this->db = $db; + + if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && isset($this->fields['rowid'])) { + $this->fields['rowid']['visible'] = 0; + } + if (empty($conf->multicompany->enabled) && isset($this->fields['entity'])) { + $this->fields['entity']['enabled'] = 0; + } + + // Unset fields that are disabled + foreach ($this->fields as $key => $val) { + if (isset($val['enabled']) && empty($val['enabled'])) { + unset($this->fields[$key]); + } + } + + // Translate some data of arrayofkeyval + if (is_object($langs)) { + foreach ($this->fields as $key => $val) { + if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) { + foreach ($val['arrayofkeyval'] as $key2 => $val2) { + $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2); + } + } + } + } + } + + /** + * Create object into database + * + * @param User $user User that creates + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int 0 < if KO, ID of created object if OK + */ + public function create(User $user, bool $notrigger = false): int + { + return $this->createCommon($user, $notrigger); + } + + /** + * Load object in memory from the database + * + * @param int $id ID object + * @param string|null $ref Ref + * @return int 0 < if KO, 0 if not found, >0 if OK + */ + public function fetch($id, string $ref = null): int + { + $result = $this->fetchCommon($id, $ref); + if ($result > 0 && !empty($this->table_element_line)) { + $this->fetchLines(); + } + return $result; + } + + /** + * Load object lines in memory from the database + * + * @return int 0 < if KO, 0 if not found, >0 if OK + */ + public function fetchLines(): int + { + $this->lines = array(); + return $this->fetchLinesCommon(); + } + + /** + * Load list of objects in memory from the database. + * + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit Limit + * @param int $offset Offset + * @param array $filter Filter array. Example array('field'=>'value', 'customurl'=>...) + * @param string $filtermode Filter mode (AND/OR) + * @return array|int int <0 if KO, array of pages if OK + * @throws Exception + */ + public function fetchAll(string $sortorder = '', string $sortfield = '', int $limit = 0, int $offset = 0, array $filter = array(), string $filtermode = 'AND') + { + dol_syslog(__METHOD__, LOG_DEBUG); + + $records = array(); + + $sql = "SELECT "; + $sql .= $this->getFieldList('t'); + $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t"; + if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) { + $sql .= " WHERE t.entity IN (".getEntity($this->element).")"; + } else { + $sql .= " WHERE 1 = 1"; + } + // Manage filter + $sqlwhere = array(); + if (count($filter) > 0) { + foreach ($filter as $key => $value) { + if ($key == 't.rowid') { + $sqlwhere[] = $key." = ".((int) $value); + } elseif (in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { + $sqlwhere[] = $key." = '".$this->db->idate($value)."'"; + } elseif ($key == 'customsql') { + $sqlwhere[] = $value; + } elseif (strpos($value, '%') === false) { + $sqlwhere[] = $key." IN (".$this->db->sanitize($this->db->escape($value)).")"; + } else { + $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'"; + } + } + } + if (count($sqlwhere) > 0) { + $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + } + + if (!empty($sortfield)) { + $sql .= $this->db->order($sortfield, $sortorder); + } + if (!empty($limit)) { + $sql .= $this->db->plimit($limit, $offset); + } + + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + $i = 0; + while ($i < ($limit ? min($limit, $num) : $num)) { + $obj = $this->db->fetch_object($resql); + + $record = new self($this->db); + $record->setVarsFromFetchObj($obj); + + $records[$record->id] = $record; + + $i++; + } + $this->db->free($resql); + + return $records; + } else { + $this->errors[] = 'Error '.$this->db->lasterror(); + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + + return -1; + } + } + + /** + * Update object into database + * + * @param User $user User that modifies + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int 0 < if KO, >0 if OK + */ + public function update(User $user, bool $notrigger = false): int + { + return $this->updateCommon($user, $notrigger); + } + + /** + * Delete object in database + * + * @param User $user User that deletes + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int 0 < if KO, >0 if OK + */ + public function delete(User $user, bool $notrigger = false): int + { + return $this->deleteCommon($user, $notrigger); + } + + /** + * Delete a line of object in database + * + * @param User $user User that delete + * @param int $idline ID of line to delete + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int >0 if OK, <0 if KO + */ + public function deleteLine(User $user, int $idline, bool $notrigger = false): int + { + if ($this->status < 0) { + $this->error = 'ErrorDeleteLineNotAllowedByObjectStatus'; + return -2; + } + + return $this->deleteLineCommon($user, $idline, $notrigger); + } + + /** + * Validate object + * + * @param User $user User making status change + * @param int $notrigger 1=Does not execute triggers, 0= execute triggers + * @return int 0 < if OK, 0=Nothing done, >0 if KO + * @throws Exception + */ + public function validate(User $user, int $notrigger = 0): int + { + global $conf; + + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + + $error = 0; + + // Protection + if ($this->status == self::STATUS_VALIDATED) { + dol_syslog(get_class($this)."::validate action abandonned: already validated", LOG_WARNING); + return 0; + } + + $now = dol_now(); + + $this->db->begin(); + + // Define new ref + if ((preg_match('/^\(?PROV/i', $this->ref) || empty($this->ref))) { // empty should not happen, but when it occurs, the test save life + $num = $this->getNextNumRef(); + } else { + $num = $this->ref; + } + $this->newref = $num; + + if (!empty($num)) { + // Validate + $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element; + $sql .= " SET ref = '".$this->db->escape($num)."',"; + $sql .= " status = ".self::STATUS_VALIDATED; + if (!empty($this->fields['date_validation'])) { + $sql .= ", date_validation = '".$this->db->idate($now)."'"; + } + if (!empty($this->fields['fk_user_valid'])) { + $sql .= ", fk_user_valid = ".((int) $user->id); + } + $sql .= " WHERE rowid = ".($this->id); + + dol_syslog(get_class($this)."::validate()", LOG_DEBUG); + $resql = $this->db->query($sql); + if (!$resql) { + dol_print_error($this->db); + $this->error = $this->db->lasterror(); + $error++; + } + + if (!$error && !$notrigger) { + // Call trigger + $result = $this->call_trigger('TIMESHEET_VALIDATE', $user); + if ($result < 0) { + $error++; + } + // End call triggers + } + } + + if (!$error) { + $this->oldref = $this->ref; + + // Rename directory if dir was a temporary ref + if (preg_match('/^\(?PROV/i', $this->ref)) { + // Now we rename also files into index + $sql = 'UPDATE '.MAIN_DB_PREFIX."ecm_files set filename = CONCAT('".$this->db->escape($this->newref)."', SUBSTR(filename, ".(strlen($this->ref) + 1).")), filepath = 'timesheet/".$this->db->escape($this->newref)."'"; + $sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%' AND filepath = 'timesheet/".$this->db->escape($this->ref)."' and entity = ".$conf->entity; + $resql = $this->db->query($sql); + if (!$resql) { + $error++; $this->error = $this->db->lasterror(); + } + + // We rename directory ($this->ref = old ref, $num = new ref) in order not to lose the attachments + $oldref = dol_sanitizeFileName($this->ref); + $newref = dol_sanitizeFileName($num); + $dirsource = $conf->dolisirh->dir_output.'/timesheet/'.$oldref; + $dirdest = $conf->dolisirh->dir_output.'/timesheet/'.$newref; + if (!$error && file_exists($dirsource)) { + dol_syslog(get_class($this)."::validate() rename dir ".$dirsource." into ".$dirdest); + + if (@rename($dirsource, $dirdest)) { + dol_syslog("Rename ok"); + // Rename docs starting with $oldref with $newref + $listoffiles = dol_dir_list($conf->dolisirh->dir_output.'/timesheet/'.$newref, 'files', 1, '^'.preg_quote($oldref, '/')); + foreach ($listoffiles as $fileentry) { + $dirsource = $fileentry['name']; + $dirdest = preg_replace('/^'.preg_quote($oldref, '/').'/', $newref, $dirsource); + $dirsource = $fileentry['path'].'/'.$dirsource; + $dirdest = $fileentry['path'].'/'.$dirdest; + @rename($dirsource, $dirdest); + } + } + } + } + } + + // Set new ref and current status + if (!$error) { + $this->ref = $num; + $this->status = self::STATUS_VALIDATED; + } + + if (!$error) { + $this->db->commit(); + return 1; + } else { + $this->db->rollback(); + return -1; + } + } + + /** + * Set draft status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int 0 < if KO, >0 if OK + * @throws Exception + */ + public function setDraft(User $user, int $notrigger = 0): int + { + // Protection + if ($this->status <= self::STATUS_DRAFT) { + return 0; + } + + $signatory = new TimeSheetSignature($this->db); + $signatory->deleteSignatoriesSignatures($this->id, 'timesheet'); + return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'TIMESHEET_UNVALIDATE'); + } + + /** + * Set locked status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int 0 < if KO, 0=Nothing done, >0 if OK + */ + public function setLocked(User $user, int $notrigger = 0): int + { + return $this->setStatusCommon($user, self::STATUS_LOCKED, $notrigger, 'TIMESHEET_LOCKED'); + } + + /** + * Set archived status + * + * @param User $user Object user that modify + * @param int $notrigger 1=Does not execute triggers, 0=Execute triggers + * @return int 0 < if KO, >0 if OK + */ + public function setArchived(User $user, int $notrigger = 0): int + { + return $this->setStatusCommon($user, self::STATUS_ARCHIVED, $notrigger, 'TIMESHEET_ARCHIVED'); + } + + /** + * Return a link to the object card (with optionaly the picto) + * + * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto) + * @param string $option On what the link point to ('nolink', ...) + * @param int $notooltip 1=Disable tooltip + * @param string $morecss Add more css on link + * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking + * @return string String with URL + */ + public function getNomUrl(int $withpicto = 0, string $option = '', int $notooltip = 0, string $morecss = '', int $save_lastsearch_value = -1): string + { + global $conf, $langs; + + if (!empty($conf->dol_no_mouse_hover)) { + $notooltip = 1; // Force disable tooltips + } + + $result = ''; + + $label = ' '.$langs->trans("TimeSheet").''; + if (isset($this->status)) { + $label .= ' '.$this->getLibStatut(5); + } + $label .= '
'; + $label .= ''.$langs->trans('Ref').': '.$this->ref; + + $url = dol_buildpath('/dolisirh/view/timesheet/timesheet_card.php', 1).'?id='.$this->id; + + if ($option != 'nolink') { + // Add param to save lastsearch_values or not + $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0); + if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) { + $add_save_lastsearch_values = 1; + } + if ($url && $add_save_lastsearch_values) { + $url .= '&save_lastsearch_values=1'; + } + } + + $linkclose = ''; + if (empty($notooltip)) { + if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) { + $label = $langs->trans("ShowTimeSheet"); + $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"'; + } + $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"'; + $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"'; + } else { + $linkclose = ($morecss ? ' class="'.$morecss.'"' : ''); + } + + if ($option == 'nolink' || empty($url)) { + $linkstart = ''; + if ($option == 'nolink' || empty($url)) { + $linkend = ''; + } else { + $linkend = ''; + } + + $result .= $linkstart; + + if ($withpicto) $result .= '' . ' '; + if ($withpicto != 2) { + $result .= $this->ref; + } + + $result .= $linkend; + //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : ''); + + global $action, $hookmanager; + $hookmanager->initHooks(array('timesheetdao')); + $parameters = array('id'=>$this->id, 'getnomurl'=>$result); + $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + if ($reshook > 0) { + $result = $hookmanager->resPrint; + } else { + $result .= $hookmanager->resPrint; + } + + return $result; + } + + /** + * Return the label of the status + * + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto + * @return string Label of status + */ + public function getLibStatut(int $mode = 0): string + { + return $this->LibStatut($this->status, $mode); + } + + /** + * Return the status + * + * @param int $status Id status + * @param int $mode 0=long label, 1=short label, 2=Picto + short label, 3=Picto, 4=Picto + long label, 5=Short label + Picto, 6=Long label + Picto + * @return string Label of status + */ + public function LibStatut(int $status, int $mode = 0): string + { + // phpcs:enable + if (empty($this->labelStatus) || empty($this->labelStatusShort)) { + global $langs; + $langs->load("dolisirh@dolisirh"); + $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('StatusDraft'); + $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('ValidatePendingSignature'); + $this->labelStatus[self::STATUS_LOCKED] = $langs->transnoentitiesnoconv('Locked'); + $this->labelStatus[self::STATUS_ARCHIVED] = $langs->transnoentitiesnoconv('Archived'); + + $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('StatusDraft'); + $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('ValidatePendingSignature'); + $this->labelStatusShort[self::STATUS_LOCKED] = $langs->transnoentitiesnoconv('Locked'); + $this->labelStatusShort[self::STATUS_ARCHIVED] = $langs->transnoentitiesnoconv('Archived'); + } + + $statusType = 'status' . $status; + if ($status == self::STATUS_VALIDATED) $statusType = 'status3'; + if ($status == self::STATUS_LOCKED) $statusType = 'status8'; + if ($status == self::STATUS_ARCHIVED) $statusType = 'status8'; + + return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode); + } + + /** + * Load the info information in the object + * + * @param int $id ID of object + * @return void + */ + public function info(int $id) + { + $sql = "SELECT rowid, date_creation as datec, tms as datem,"; + $sql .= " fk_user_creat, fk_user_modif"; + $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element." as t"; + $sql .= " WHERE t.rowid = ".($id); + + $result = $this->db->query($sql); + if ($result) { + if ($this->db->num_rows($result)) { + $obj = $this->db->fetch_object($result); + $this->id = $obj->rowid; + + $this->date_creation = $this->db->jdate($obj->date_creation); + } + + $this->db->free($result); + } else { + dol_print_error($this->db); + } + } + + /** + * Initialise object with example values + * ID must be 0 if object instance is a specimen + * + * @return void + */ + public function initAsSpecimen() + { + // Set here init that are not common fields + // $this->property1 = ... + // $this->property2 = ... + + $this->initAsSpecimenCommon(); + } + + /** + * Create an array of lines + * + * @return array|int array of lines if OK, <0 if KO + * @throws Exception + */ + public function getLinesArray() + { + $this->lines = array(); + + $objectline = new TimeSheetLine($this->db); + $result = $objectline->fetchAll('ASC', 'rang', 0, 0, array('customsql'=>'fk_timesheet = '.($this->id))); + + if (is_numeric($result)) { + $this->error = $objectline->error; + $this->errors = $objectline->errors; + return $result; + } else { + $this->lines = $result; + return $this->lines; + } + } + + /** + * Returns the reference to the following non-used object depending on the active numbering module. + * + * @return string Object free reference + */ + public function getNextNumRef(): string + { + global $langs, $conf; + $langs->load("dolisirh@dolisirh"); + + if (empty($conf->global->DOLISIRH_TIMESHEET_ADDON)) { + $conf->global->DOLISIRH_TIMESHEET_ADDON = 'mod_timesheet_standard'; + } + + if (!empty($conf->global->DOLISIRH_TIMESHEET_ADDON)) { + $mybool = false; + + $file = $conf->global->DOLISIRH_TIMESHEET_ADDON.".php"; + $classname = $conf->global->DOLISIRH_TIMESHEET_ADDON; + + // Include file with class + $dirmodels = array_merge(array('/'), $conf->modules_parts['models']); + foreach ($dirmodels as $reldir) { + $dir = dol_buildpath($reldir."core/modules/dolisirh/timesheet/"); + + // Load file with numbering class (if found) + $mybool |= @include_once $dir.$file; + } + + if ($mybool === false) { + dol_print_error('', "Failed to include file ".$file); + return ''; + } + + if (class_exists($classname)) { + $obj = new $classname(); + $numref = $obj->getNextValue($this); + + if ($numref != '' && $numref != '-1') { + return $numref; + } else { + $this->error = $obj->error; + //dol_print_error($this->db,get_class($this)."::getNextNumRef ".$obj->error); + return ""; + } + } else { + print $langs->trans("Error")." ".$langs->trans("ClassNotFound").' '.$classname; + return ""; + } + } else { + print $langs->trans("ErrorNumberingModuleNotSetup", $this->element); + return ""; + } + } + + /** + * Sets object to supplied categories. + * + * Deletes object from existing categories not supplied. + * Adds it to non-existing supplied categories. + * Existing categories are left untouched. + * + * @param int[]|int $categories Category or categories IDs + * @return float|int + */ + public function setCategories($categories) + { + return parent::setCategoriesCommon($categories, 'timesheet'); + } + + /** + * Create a document onto disk according to template module. + * + * @param string $modele Force template to use ('' to not force) + * @param Translate $outputlangs Objet lang use for translate + * @param int $hidedetails Hide details of lines + * @param int $hidedesc Hide description + * @param int $hideref Hide ref + * @param array|null $moreparams Array to provide more information + * @return int 0 if KO, 1 if OK + */ + public function generateDocument(string $modele, Translate $outputlangs, int $hidedetails = 0, int $hidedesc = 0, int $hideref = 0, array $moreparams = null): int + { + global $conf, $langs; + + $result = 0; + + $langs->load("dolisirh@dolisirh"); + + if (!dol_strlen($modele)) { + $modele = 'standard_timesheet'; + + if (!empty($this->model_pdf)) { + $modele = $this->model_pdf; + } elseif (!empty($conf->global->TIMESHEET_ADDON_PDF)) { + $modele = $conf->global->TIMESHEET_ADDON_PDF; + } + } + + $modelpath = "core/modules/dolisirh/timesheetdocument/"; + + if (!empty($modele)) { + $result = $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams['object']); + } + + return $result; + } +} + +require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php'; + +/** + * Class TimeSheetLine. You can also remove this and generate a CRUD class for lines objects. + */ +class TimeSheetLine extends CommonObjectLine +{ + /** + * @var DoliDB Database handler. + */ + public $db; + + /** + * @var string Error string + */ + public $error; + + /** + * @var int The object identifier + */ + public $id; + + /** + * @var string ID to identify managed object + */ + public $element = 'fk_timesheetdet'; + + /** + * @var string Name of table without prefix where object is stored + */ + public $table_element = 'dolisirh_timesheetdet'; + + /** + * @var int Does object support extrafields ? 0=No, 1=Yes + */ + public $isextrafieldmanaged = 0; + + /** + * 'type' field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]', 'sellist:TableName:LabelFieldName[:KeyFieldName[:KeyFieldParent[:Filter[:Sortfield]]]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'text:none', 'html', 'date', 'datetime', 'timestamp', 'duration', 'mail', 'phone', 'url', 'password') + * Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:<:'20160101') or (t.nature:is:NULL)" + * 'label' the translation key. + * 'picto' is code of a picto to show before value in forms + * 'enabled' is a condition when the field must be managed (Example: 1 or '$conf->global->MY_SETUP_PARAM) + * 'position' is the sort order of field. + * 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0). + * 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing) + * 'noteditable' says if field is not editable (1 or 0) + * 'default' is a default value for creation (can still be overwroted by the Setup of Default Values if field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created. + * 'index' if we want an index in database. + * 'foreignkey'=>'tablename.field' if the field is a foreign key (it is recommanded to name the field fk_...). + * 'searchall' is 1 if we want to search in this field when making a search from the quick search button. + * 'isameasure' must be set to 1 or 2 if field can be used for measure. Field type must be summable like integer or double(24,8). Use 1 in most cases, or 2 if you don't want to see the column total into list (for example for percentage) + * 'css' and 'cssview' and 'csslist' is the CSS style to use on field. 'css' is used in creation and update. 'cssview' is used in view mode. 'csslist' is used for columns in lists. For example: 'css'=>'minwidth300 maxwidth500 widthcentpercentminusx', 'cssview'=>'wordbreak', 'csslist'=>'tdoverflowmax200' + * 'help' is a 'TranslationString' to use to show a tooltip on field. You can also use 'TranslationString:keyfortooltiponlick' for a tooltip on click. + * 'showoncombobox' if value of the field must be visible into the label of the combobox that list record + * 'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code. + * 'arrayofkeyval' to set a list of values if type is a list of predefined values. For example: array("0"=>"Draft","1"=>"Active","-1"=>"Cancel"). Note that type can be 'integer' or 'varchar' + * 'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1. + * 'comment' is not used. You can store here any text of your choice. It is not used by application. + * 'validate' is 1 if you need to validate with $this->validateField() + * 'copytoclipboard' is 1 or 2 to allow to add a picto to copy value into clipboard (1=picto after label, 2=picto after value) + * + * Note: To have value dynamic, you can set value to 0 in definition and edit the value on the fly into the constructor. + */ + + /** + * @var array Array with all fields and their property. Do not use it as a static var. It may be modified by constructor. + */ + public $fields = array( + 'rowid' => array('type'=>'integer', 'label'=>'TechnicalID', 'enabled'=>'1', 'position'=>1, 'notnull'=>1, 'visible'=>0, 'noteditable'=>'1', 'index'=>1, 'css'=>'left', 'comment'=>"Id"), + 'date_creation' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>'1', 'position'=>10, 'notnull'=>1, 'visible'=>0,), + 'qty' => array('type'=>'real', 'label'=>'Quantity', 'enabled'=>'1', 'position'=>20, 'notnull'=>0, 'visible'=>0,), + 'rang' => array('type'=>'integer', 'label'=>'Order', 'enabled'=>'1', 'position'=>30, 'notnull'=>0, 'visible'=>0, 'default'=>0,), + 'description' => array('type'=>'html', 'label'=>'Description', 'enabled'=>'1', 'position'=>40, 'notnull'=>0, 'visible'=>0,), + 'product_type' => array('type'=>'integer', 'label'=>'ProductType', 'enabled'=>'1', 'position'=>50, 'notnull'=>0, 'visible'=>0,'default'=>0,), + 'fk_timesheet' => array('type'=>'integer:TimeSheet:custom/dolisirh/class/timesheet.class.php:1', 'label'=>'TimeSheet', 'enabled'=>'1', 'position'=>60, 'notnull'=>1, 'visible'=>0,), + 'fk_product' => array('type'=>'integer:Product:product/class/product.class.php:1', 'label'=>'Product', 'enabled'=>'1', 'position'=>70, 'notnull'=>-1, 'visible'=>0,), + 'fk_parent_line' => array('type'=>'integer:Product:product/class/product.class.php:1', 'label'=>'ParentProductLine', 'enabled'=>'1', 'position'=>80, 'notnull'=>-1, 'visible'=>0,), + ); + + public $rowid; + public $date_creation; + public $qty; + public $rang; + public $description; + public $product_type; + public $fk_timesheet; + public $fk_product; + public $fk_parent_line; + + /** + * Constructor + * + * @param DoliDb $db Database handler + */ + public function __construct(DoliDB $db) + { + $this->db = $db; + } + + /** + * Load time sheet line from database + * + * @param int $rowid ID of timesheet line to get + * @return int 0 < if KO, >0 if OK + */ + public function fetch(int $rowid): int + { + $sql = 'SELECT tsd.rowid, tsd.date_creation, tsd.qty, tsd.rang, tsd.description, tsd.product_type,'; + $sql .= ' tsd.fk_timesheet, tsd.fk_product, tsd.fk_parent_line'; + $sql .= ' FROM ' . MAIN_DB_PREFIX . 'dolisirh_timesheetdet as tsd'; + $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON tsd.fk_product = p.rowid'; + $sql .= ' WHERE tsd.rowid = ' . $rowid; + + $result = $this->db->query($sql); + if ($result) { + $objp = $this->db->fetch_object($result); + + $this->id = $objp->rowid; + $this->date_creation = $objp->date_creation; + $this->qty = $objp->qty; + $this->rang = $objp->rang; + $this->description = $objp->description; + $this->product_type = $objp->product_type; + $this->fk_timesheet = $objp->fk_timesheet; + $this->fk_product = $objp->fk_product; + $this->fk_parent_line = $objp->fk_parent_line; + + $this->db->free($result); + + return $this->id; + } else { + $this->error = $this->db->lasterror(); + return -1; + } + } + + /** + * Load timesheet line from database + * + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit Offset limit + * @param int $offset Offset limit + * @param array $filter Filter array + * @param string $filtermode Filter mode (AND/OR) + * @param int $parent_id Parent ID + * @return array|int + * @throws Exception + */ + public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND', int $parent_id = 0) + { + $sql = 'SELECT tsd.rowid, tsd.date_creation, tsd.qty, tsd.rang, tsd.description, tsd.product_type,'; + $sql .= ' tsd.fk_timesheet, tsd.fk_product, tsd.fk_parent_line'; + $sql .= ' FROM ' . MAIN_DB_PREFIX . 'dolisirh_timesheetdet as tsd'; + $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product as p ON tsd.fk_product = p.rowid'; + if ($parent_id > 0) { + $sql .= ' WHERE tsd.fk_timesheet = ' . $parent_id; + } else { + $sql .= ' WHERE 1=1'; + } + // Manage filter + $sqlwhere = array(); + if (count($filter) > 0) { + foreach ($filter as $key => $value) { + if ($key == 't.rowid') { + $sqlwhere[] = $key." = ".((int) $value); + } elseif (in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { + $sqlwhere[] = $key." = '".$this->db->idate($value)."'"; + } elseif ($key == 'customsql') { + $sqlwhere[] = $value; + } elseif (strpos($value, '%') === false) { + $sqlwhere[] = $key." IN (".$this->db->sanitize($this->db->escape($value)).")"; + } else { + $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'"; + } + } + } + if (count($sqlwhere) > 0) { + $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + } + + if (!empty($sortfield)) { + $sql .= $this->db->order($sortfield, $sortorder); + } + if (!empty($limit)) { + $sql .= $this->db->plimit($limit, $offset); + } + + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + $i = 0; + while ($i < ($limit ? min($limit, $num) : $num)) { + $obj = $this->db->fetch_object($resql); + + $record = new self($this->db); + $record->setVarsFromFetchObj($obj); + + $records[$record->id] = $record; + + $i++; + } + $this->db->free($resql); + + if (!empty($records)) { + return $records; + } + } else { + $this->errors[] = 'Error '.$this->db->lasterror(); + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + + return -1; + } + } + + /** + * Insert line into database + * + * @param User $user + * @param bool $notrigger 1 no triggers + * @return int 0 < if KO, >0 if OK + * @throws Exception + */ + public function insert(User $user, bool $notrigger = false): int + { + global $user; + + // Clean parameters + $this->description = trim($this->description); + + $this->db->begin(); + $now = dol_now(); + + // Insertion dans base de la line + $sql = 'INSERT INTO ' . MAIN_DB_PREFIX . 'dolisirh_timesheetdet'; + $sql .= ' (date_creation, qty, rang, description, product_type,'; + $sql .= ' fk_timesheet, fk_product, fk_parent_line)'; + $sql .= " VALUES ("; + $sql .= "'" . $this->db->escape($this->db->idate($now)) . "'" . ", "; + $sql .= price2num($this->qty, 'MS') . ", "; + $sql .= $this->rang . ", "; + $sql .= "'" . $this->db->escape($this->description) . "'" . ", "; + $sql .= "'" . $this->db->escape($this->product_type) . "'" . ", "; + $sql .= $this->fk_timesheet . ", "; + $sql .= ($this->fk_product ? "'".$this->db->escape($this->fk_product)."'" : "null") . ", "; + $sql .= ($this->fk_parent_line > 0 ? "'".$this->db->escape($this->fk_parent_line)."'" : "null"); + $sql .= ')'; + + dol_syslog(get_class($this) . "::insert", LOG_DEBUG); + $resql = $this->db->query($sql); + + if ($resql) { + $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX . 'timesheetdet'); + $this->rowid = $this->id; // For backward compatibility + + $this->db->commit(); + // Triggers + if ( ! $notrigger) { + // Call triggers + $this->call_trigger(strtoupper(get_class($this)) . '_CREATE', $user); + // End call triggers + } + return $this->id; + } else { + $this->error = $this->db->lasterror(); + $this->db->rollback(); + return -2; + } + } + + /** + * Update line into database + * + * @param User $user User object + * @param bool $notrigger Disable triggers + * @return int 0 < if KO, >0 if OK + * @throws Exception + */ + public function update(User $user, bool $notrigger = false): int + { + global $user; + + // Clean parameters + $this->description = trim($this->description); + + $this->db->begin(); + + $sql = "UPDATE " . MAIN_DB_PREFIX . "dolisirh_timesheetdet SET"; + $sql .= " qty = " . $this->qty . ","; + if (!empty($this->rang)) { + $sql .= " rang = " . $this->rang . ","; + } + $sql .= " description='" . $this->db->escape($this->description) . "'"; + + $sql .= " WHERE rowid = " . $this->id; + + dol_syslog(get_class($this) . "::update", LOG_DEBUG); + $resql = $this->db->query($sql); + + if ($resql) { + $this->db->commit(); + // Triggers + if ( ! $notrigger) { + // Call triggers + $this->call_trigger(strtoupper(get_class($this)) . '_MODIFY', $user); + // End call triggers + } + return $this->id; + } else { + $this->error = $this->db->error(); + $this->db->rollback(); + return -2; + } + } + + /** + * Delete line in database + * + * @param User $user User object + * @param bool $notrigger Disable triggers + * @return int 0 0 if OK + * @throws Exception + */ + public function delete(User $user, bool $notrigger = false): int + { + global $user; + + $this->db->begin(); + + $sql = "DELETE FROM " . MAIN_DB_PREFIX . "dolisirh_timesheetdet WHERE rowid = " . $this->id; + dol_syslog(get_class($this) . "::delete", LOG_DEBUG); + if ($this->db->query($sql)) { + $this->db->commit(); + // Triggers + if ( ! $notrigger) { + // Call trigger + $this->call_trigger(strtoupper(get_class($this)) . '_DELETE', $user); + // End call triggers + } + return 1; + } else { + $this->error = $this->db->error() . " sql=" . $sql; + $this->db->rollback(); + return -1; + } + } +} + +/** + * Class TimeSheetSignature + */ + +class TimeSheetSignature extends DoliSIRHSignature +{ + /** + * @var string Name of table without prefix where object is stored. This is also the key used for extrafields management. + */ + + public $object_type = 'timesheet'; + + /** + * @var array Context element object + */ + public $context = array(); + + /** + * @var string String with name of icon for document. Must be the part after the 'object_' into object_document.png + */ + public $picto = 'timesheet@dolisirh'; + + /** + * Constructor + * + * @param DoliDb $db Database handler + */ + public function __construct(DoliDB $db) + { + global $conf, $langs; + + $this->db = $db; + + if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && isset($this->fields['rowid'])) $this->fields['rowid']['visible'] = 0; + if (empty($conf->multicompany->enabled) && isset($this->fields['entity'])) $this->fields['entity']['enabled'] = 0; + + // Unset fields that are disabled + foreach ($this->fields as $key => $val) { + if (isset($val['enabled']) && empty($val['enabled'])) { + unset($this->fields[$key]); + } + } + + // Translate some data of arrayofkeyval + if (is_object($langs)) { + foreach ($this->fields as $key => $val) { + if (is_array($val['arrayofkeyval'])) { + foreach ($val['arrayofkeyval'] as $key2 => $val2) { + $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2); + } + } + } + } + } +} + diff --git a/class/workinghours.class.php b/class/workinghours.class.php new file mode 100644 index 0000000..c51577f --- /dev/null +++ b/class/workinghours.class.php @@ -0,0 +1,280 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file class/workinghours.class.php + * \ingroup dolisirh + * \brief This file is a CRUD class file for Workinghours (Create/Read/Update/Delete) + */ + +require_once DOL_DOCUMENT_ROOT . '/core/class/commonobject.class.php'; + +/** + * Class for Workinghours + */ +class Workinghours extends CommonObject +{ + /** + * @var DoliDB Database handler. + */ + public $db; + + /** + * @var string ID to identify managed object. + */ + public $element = 'workinghours'; + + /** + * @var string Name of table without prefix where object is stored. This is also the key used for extrafields management. + */ + public $table_element = 'element_workinghours'; + + /** + * @var int Does this object support multicompany module ? + * 0=No test on entity, 1=Test with field entity, 'field@table'=Test with link by field@table + */ + public $ismultientitymanaged = 1; + + /** + * @var int Does object support extrafields ? 0=No, 1=Yes + */ + public $isextrafieldmanaged = 1; + + /** + * @var string String with name of icon for workinghours. Must be the part after the 'object_' into object_workinghours.png + */ + public $picto = 'workinghours@dolisirh'; + + /** + * @var array Array with all fields and their property. Do not use it as a static var. It may be modified by constructor. + */ + public $fields = array( + 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => '1', 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => '1', 'index' => 1, 'comment' => "Id"), + 'entity' => array('type' => 'integer', 'label' => 'Entity', 'enabled' => '1', 'position' => 10, 'notnull' => 1, 'visible' => -1,), + 'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => '1', 'position' => 20, 'notnull' => 1, 'visible' => -2,), + 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => '1', 'position' => 30, 'notnull' => 0, 'visible' => -2,), + 'status' => array('type' => 'smallint', 'label' => 'Status', 'enabled' => '1', 'position' => 40, 'notnull' => 0, 'visible' => -1,), + 'element_type' => array('type' => 'varchar(50)', 'label' => 'ElementType', 'enabled' => '1', 'position' => 50, 'notnull' => 0, 'visible' => -1,), + 'element_id' => array('type' => 'integer', 'label' => 'ElementID', 'enabled' => '1', 'position' => 60, 'notnull' => 1, 'visible' => -1,), + 'schedule_monday' => array('type' => 'varchar(128)', 'label' => 'Day 0', 'enabled' => '1', 'position' => 70, 'notnull' => 0, 'visible' => 1,), + 'schedule_tuesday' => array('type' => 'varchar(128)', 'label' => 'Day 1', 'enabled' => '1', 'position' => 80, 'notnull' => 0, 'visible' => 1,), + 'schedule_wednesday' => array('type' => 'varchar(128)', 'label' => 'Day 2', 'enabled' => '1', 'position' => 90, 'notnull' => 0, 'visible' => 1,), + 'schedule_thursday' => array('type' => 'varchar(128)', 'label' => 'Day 3', 'enabled' => '1', 'position' => 100, 'notnull' => 0, 'visible' => 1,), + 'schedule_friday' => array('type' => 'varchar(128)', 'label' => 'Day 4', 'enabled' => '1', 'position' => 110, 'notnull' => 0, 'visible' => 1,), + 'schedule_saturday' => array('type' => 'varchar(128)', 'label' => 'Day 5', 'enabled' => '1', 'position' => 120, 'notnull' => 0, 'visible' => 1,), + 'schedule_sunday' => array('type' => 'varchar(128)', 'label' => 'Day 6', 'enabled' => '1', 'position' => 130, 'notnull' => 0, 'visible' => 1,), + 'workinghours_monday' => array('type' => 'integer', 'label' => 'Day 0', 'enabled' => '1', 'position' => 170, 'notnull' => 0, 'visible' => 1,), + 'workinghours_tuesday' => array('type' => 'integer', 'label' => 'Day 1', 'enabled' => '1', 'position' => 180, 'notnull' => 0, 'visible' => 1,), + 'workinghours_wednesday' => array('type' => 'integer', 'label' => 'Day 2', 'enabled' => '1', 'position' => 190, 'notnull' => 0, 'visible' => 1,), + 'workinghours_thursday' => array('type' => 'integer', 'label' => 'Day 3', 'enabled' => '1', 'position' => 200, 'notnull' => 0, 'visible' => 1,), + 'workinghours_friday' => array('type' => 'integer', 'label' => 'Day 4', 'enabled' => '1', 'position' => 210, 'notnull' => 0, 'visible' => 1,), + 'workinghours_saturday' => array('type' => 'integer', 'label' => 'Day 5', 'enabled' => '1', 'position' => 220, 'notnull' => 0, 'visible' => 1,), + 'workinghours_sunday' => array('type' => 'integer', 'label' => 'Day 6', 'enabled' => '1', 'position' => 230, 'notnull' => 0, 'visible' => 1,), + 'fk_user_creat' => array('type' => 'integer:User:user/class/user.class.php', 'label' => 'UserAuthor', 'enabled' => '1', 'position' => 140, 'notnull' => 1, 'visible' => -2, 'foreignkey' => 'user.rowid',), + ); + + public $rowid; + public $entity; + public $date_creation; + public $tms; + public $status; + public $element_type; + public $element_id; + public $schedule_monday; + public $schedule_tuesday; + public $schedule_wednesday; + public $schedule_thursday; + public $schedule_friday; + public $schedule_saturday; + public $schedule_sunday; + public $workinghours_monday; + public $workinghours_tuesday; + public $workinghours_wednesday; + public $workinghours_thursday; + public $workinghours_friday; + public $workinghours_saturday; + public $workinghours_sunday; + public $fk_user_creat; + + /** + * Constructor + * + * @param DoliDb $db Database handler + */ + public function __construct(DoliDB $db) + { + global $conf, $langs; + + $this->db = $db; + + if (empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && isset($this->fields['rowid'])) $this->fields['rowid']['visible'] = 0; + if (empty($conf->multicompany->enabled) && isset($this->fields['entity'])) $this->fields['entity']['enabled'] = 0; + + // Unset fields that are disabled + foreach ($this->fields as $key => $val) { + if (isset($val['enabled']) && empty($val['enabled'])) { + unset($this->fields[$key]); + } + } + + // Translate some data of arrayofkeyval + if (is_object($langs)) { + foreach ($this->fields as $key => $val) { + if (is_array($val['arrayofkeyval'])) { + foreach ($val['arrayofkeyval'] as $key2 => $val2) { + $this->fields[$key]['arrayofkeyval'][$key2] = $langs->trans($val2); + } + } + } + } + } + + /** + * Create object into database + * + * @param User $user User that creates + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int 0 < if KO, ID of created object if OK + * @throws Exception + */ + public function create(User $user, bool $notrigger = false): int + { + $sql = "UPDATE " . MAIN_DB_PREFIX . "$this->table_element"; + $sql .= " SET status = 0"; + if (isset($this->ismultientitymanaged) && $this->ismultientitymanaged == 1) $sql .= ' WHERE entity IN (' . getEntity($this->table_element) . ')'; + else $sql .= ' WHERE 1 = 1'; + $sql .= " AND element_type = " . "'" . $this->element_type . "'"; + $sql .= " AND element_id = " . $this->element_id; + + dol_syslog("admin.lib::create", LOG_DEBUG); + $this->db->query($sql); + return $this->createCommon($user, $notrigger); + } + + /** + * Load object in memory from the database + * + * @param int $id ID object + * @param string|null $ref Ref + * @param string $morewhere More SQL filters (' AND ...') + * @return int 0 < if KO, 0 if not found, >0 if OK + */ + public function fetch(int $id, string $ref = null, string $morewhere = ''): int + { + return $this->fetchCommon($id, $ref, $morewhere); + } + + /** + * Load list of objects in memory from the database. + * + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit Limit + * @param int $offset Offset + * @param array $filter Filter array. Example array('field'=>'value', 'customurl'=>...) + * @param string $filtermode Filter mode (AND/OR) + * @return array|int int <0 if KO, array of pages if OK + * @throws Exception + */ + public function fetchAll(string $sortorder = '', string $sortfield = '', int $limit = 0, int $offset = 0, array $filter = array(), string $filtermode = 'AND') + { + dol_syslog(__METHOD__, LOG_DEBUG); + + $records = array(); + + $sql = 'SELECT '; + $sql .= $this->getFieldList(); + $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; + if ($this->ismultientitymanaged) { + $sql .= ' WHERE t.entity IN ('.getEntity($this->table_element).')'; + } else { + $sql .= ' WHERE 1 = 1'; + } + // Manage filter + $sqlwhere = array(); + if (count($filter) > 0) { + foreach ($filter as $key => $value) { + if ($key == 't.rowid') { + $sqlwhere[] = $key." = ".((int) $value); + } elseif (strpos($key, 'date') !== false) { + $sqlwhere[] = $key." = '".$this->db->idate($value)."'"; + } elseif ($key == 'customsql') { + $sqlwhere[] = $value; + } else { + $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'"; + } + } + } + if (count($sqlwhere) > 0) { + $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + } + + if (!empty($sortfield)) { + $sql .= $this->db->order($sortfield, $sortorder); + } + if (!empty($limit)) { + $sql .= $this->db->plimit($limit, $offset); + } + + $resql = $this->db->query($sql); + if ($resql) { + $this->db->num_rows($resql); + + while ($obj = $this->db->fetch_object($resql)) { + $record = new self($this->db); + $record->setVarsFromFetchObj($obj); + + $records[$record->id] = $record; + } + $this->db->free($resql); + + return $records; + } else { + $this->errors[] = 'Error '.$this->db->lasterror(); + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + + return -1; + } + } + + /** + * Load list of objects in memory from the database. + * + * @param int $id ID object + * @param string $type Type of object + * @return array|int int <0 if KO, array of pages if OK + * @throws Exception + */ + public function fetchCurrentWorkingHours(int $id, string $type) + { + $current_workinghours = $this->fetchAll('', '',0,0, array('element_type' => $type, 'element_id' => $id, 'status' => 1)); + if (is_array($current_workinghours) && !empty($current_workinghours)) { + $current_workinghours = array_shift($current_workinghours); + } + return $current_workinghours; + } + + /** + * Return label of contact status + * + * @return string Label of contact status + */ + public function getLibStatut(): string + { + return ''; + } +} diff --git a/core/index.php b/core/index.php new file mode 100644 index 0000000..17927e6 --- /dev/null +++ b/core/index.php @@ -0,0 +1,2 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * or see https://www.gnu.org/ + */ + +/** + * \file core/modules/dolisirh/mod_timesheet_standard.php + * \ingroup dolisirh + * \brief File of class to manage TimeSheet numbering rules standard + */ + +/** + * Class to manage customer order numbering rules standard + */ +class mod_timesheet_standard +{ + /** + * Dolibarr version of the loaded document + * @var string + */ + public $version = 'dolibarr'; // 'development', 'experimental', 'dolibarr' + + /** + * @var string document prefix + */ + public $prefix = 'TS'; + + /** + * @var string Error code (or message) + */ + public $error = ''; + + /** + * @var string name + */ + public $name = 'Skoll'; + + /** + * Return description of numbering module + * + * @return string Text with description + */ + public function info(): string + { + global $langs; + $langs->load("dolisirh@dolisirh"); + return $langs->trans("DoliSIRHTimeSheetStandardModel", $this->prefix); + } + + /** + * Return if a module can be used or not + * + * @return boolean true if module can be used + */ + public function isEnabled(): bool + { + return true; + } + + /** + * Return an example of numbering + * + * @return string Example + */ + public function getExample(): string + { + return $this->prefix."0501-0001"; + } + + /** + * Checks if the numbers already in the database do not + * cause conflicts that would prevent this numbering working. + * + * @param Object $object Object we need next value for + * @return boolean false if are conflict, true if ok + */ + public function canBeActivated(object $object): bool + { + global $conf, $langs, $db; + + $coyymm = ''; $max = ''; + + $posindice = strlen($this->prefix) + 6; + $sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max"; + $sql .= " FROM ".MAIN_DB_PREFIX."dolisirh_timesheet"; + $sql .= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'"; + if ($object->ismultientitymanaged == 1) { + $sql .= " AND entity = ".$conf->entity; + } elseif ($object->ismultientitymanaged == 2) { + // TODO + } + + $resql = $db->query($sql); + if ($resql) { + $row = $db->fetch_row($resql); + if ($row) { + $coyymm = substr($row[0], 0, 6); $max = $row[0]; + } + } + if ($coyymm && !preg_match('/'.$this->prefix.'[0-9][0-9][0-9][0-9]/i', $coyymm)) { + $langs->load("errors"); + $this->error = $langs->trans('ErrorNumRefModel', $max); + return false; + } + + return true; + } + + /** + * Return next free value + * + * @param Object $object Object we need next value for + * @return string Value if KO, <0 if KO + * @throws Exception + */ + public function getNextValue(object $object) + { + global $db, $conf; + + // first we get the max value + $posindice = strlen($this->prefix) + 6; + $sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max"; + $sql .= " FROM ".MAIN_DB_PREFIX."dolisirh_timesheet"; + $sql .= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'"; + if ($object->ismultientitymanaged == 1) { + $sql .= " AND entity = ".$conf->entity; + } elseif ($object->ismultientitymanaged == 2) { + // TODO + } + + $resql = $db->query($sql); + if ($resql) { + $obj = $db->fetch_object($resql); + if ($obj) { + $max = intval($obj->max); + } else { + $max = 0; + } + } else { + dol_syslog("mod_timesheet_standard::getNextValue", LOG_DEBUG); + return -1; + } + + //$date=time(); + $date = $object->date_creation; + $yymm = strftime("%y%m", $date); + + if ($max >= (pow(10, 4) - 1)) { + $num = $max + 1; // If counter > 9999, we do not format on 4 chars, we take number as it is + } else { + $num = sprintf("%04s", $max + 1); + } + + dol_syslog("mod_timesheet_standard::getNextValue return ".$this->prefix.$yymm."-".$num); + return $this->prefix.$yymm."-".$num; + } + + /** + * Returns version of numbering module + * + * @return string Value + */ + public function getVersion(): string + { + global $langs; + $langs->load("admin"); + + if ($this->version == 'development') { + return $langs->trans("VersionDevelopment"); + } + if ($this->version == 'experimental') { + return $langs->trans("VersionExperimental"); + } + if ($this->version == 'dolibarr') { + return DOL_VERSION; + } + if ($this->version) { + return $this->version; + } + return $langs->trans("NotAvailable"); + } +} diff --git a/core/modules/dolisirh/timesheetdocument/doc_timesheetdocument_odt.modules.php b/core/modules/dolisirh/timesheetdocument/doc_timesheetdocument_odt.modules.php new file mode 100644 index 0000000..848dc2c --- /dev/null +++ b/core/modules/dolisirh/timesheetdocument/doc_timesheetdocument_odt.modules.php @@ -0,0 +1,1042 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * or see https://www.gnu.org/ + */ + +/** + * \file core/modules/dolisirh/timesheetdocument/doc_timesheetdocument_odt.modules.php + * \ingroup dolisirh + * \brief File of class to build ODT documents for timesheet + */ + +require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; +require_once DOL_DOCUMENT_ROOT . '/core/lib/images.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/doc.lib.php'; + +require_once __DIR__ . '/modules_timesheetdocument.php'; +require_once DOL_DOCUMENT_ROOT.'/custom/dolisirh/class/workinghours.class.php'; + +/** + * Class to build documents using ODF templates generator + */ +class doc_timesheetdocument_odt extends ModeleODTTimeSheetDocument +{ + /** + * Issuer + * @var Societe + */ + public $emetteur; + + /** + * @var array Minimum version of PHP required by module. + * e.g.: PHP ≥ 5.6 = array(5, 6) + */ + public $phpmin = array(5, 6); + + /** + * @var string Dolibarr version of the loaded document + */ + public $version = 'dolibarr'; + + /** + * Constructor + * + * @param DoliDB $db Database handler + */ + public function __construct($db) + { + global $langs, $mysoc; + + // Load translation files required by the page + $langs->loadLangs(array("main", "companies")); + + $this->db = $db; + $this->name = $langs->trans('TimeSheetDocumentDoliSIRHTemplate'); + $this->description = $langs->trans("DocumentModelOdt"); + $this->scandir = 'DOLISIRH_TIMESHEETDOCUMENT_ADDON_ODT_PATH'; // Name of constant that is used to save list of directories to scan + + // Page size for A4 format + $this->type = 'odt'; + $this->page_largeur = 0; + $this->page_hauteur = 0; + $this->format = array($this->page_largeur, $this->page_hauteur); + $this->marge_gauche = 0; + $this->marge_droite = 0; + $this->marge_haute = 0; + $this->marge_basse = 0; + + $this->option_logo = 1; // Display logo + $this->option_tva = 0; // Manage the vat option FACTURE_TVAOPTION + $this->option_modereg = 0; // Display payment mode + $this->option_condreg = 0; // Display payment terms + $this->option_codeproduitservice = 0; // Display product-service code + $this->option_multilang = 1; // Available in several languages + $this->option_escompte = 0; // Displays if there has been a discount + $this->option_credit_note = 0; // Support credit notes + $this->option_freetext = 1; // Support add of a personalised text + $this->option_draft_watermark = 0; // Support add of a watermark on drafts + + // Get source company + $this->emetteur = $mysoc; + if (!$this->emetteur->country_code) { + $this->emetteur->country_code = substr($langs->defaultlang, -2); // By default if not defined + } + } + + /** + * Return description of a module + * + * @param Translate $langs Lang object to use for output + * @return string Description + */ + public function info($langs) + { + global $conf, $langs; + + // Load translation files required by the page + $langs->loadLangs(array("errors", "companies")); + + $texte = $this->description.".
\n"; + $texte .= '
'; + $texte .= ''; + $texte .= ''; + $texte .= ''; + $texte .= ''; + $texte .= ''; + + // List of directories area + $texte .= ''; + $texte .= '
'; + $texttitle = $langs->trans("ListOfDirectories"); + $listofdir = explode(',', preg_replace('/[\r\n]+/', ',', trim($conf->global->DOLISIRH_TIMESHEETDOCUMENT_ADDON_ODT_PATH))); + $listoffiles = array(); + foreach ($listofdir as $key => $tmpdir) { + $tmpdir = trim($tmpdir); + $tmpdir = preg_replace('/DOL_DATA_ROOT/', DOL_DATA_ROOT, $tmpdir); + $tmpdir = preg_replace('/DOL_DOCUMENT_ROOT/', DOL_DOCUMENT_ROOT, $tmpdir); + + if (!$tmpdir) { + unset($listofdir[$key]); + continue; + } + if (!is_dir($tmpdir)) { + $texttitle .= img_warning($langs->trans("ErrorDirNotFound", $tmpdir), 0); + } else { + $tmpfiles = dol_dir_list($tmpdir, 'files', 0, '\.(ods|odt)'); + if (count($tmpfiles)) { + $listoffiles = array_merge($listoffiles, $tmpfiles); + } + } + } + + // Scan directories + $nbofiles = count($listoffiles); + if (!empty($conf->global->DOLISIRH_TIMESHEETDOCUMENT_ADDON_ODT_PATH)) { + $texte .= $langs->trans("DoliSIRHNumberOfModelFilesFound").': '; + //$texte.=$nbofiles?'':''; + $texte .= count($listoffiles); + //$texte.=$nbofiles?'':''; + $texte .= ''; + } + + if ($nbofiles) { + $texte .= ''; + } + + $texte .= '
'; + $texte .= '
'; + + return $texte; + } + + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Function to build a document on disk using the generic odt module. + * + * @param TimeSheet $object Object source to build document + * @param Translate $outputlangs Lang output object + * @param string $srctemplatepath Full path of source filename for generator using a template file + * @param int $hidedetails Do not show line details + * @param int $hidedesc Do not show desc + * @param int $hideref Do not show ref + * @return int 1 if OK, <=0 if KO + */ + public function write_file($object, $outputlangs, $srctemplatepath, $hidedetails = 0, $hidedesc = 0, $hideref = 0) + { + // phpcs:enable + global $user, $langs, $conf, $mysoc, $hookmanager; + + if (empty($srctemplatepath)) { + dol_syslog("doc_generic_odt::write_file parameter srctemplatepath empty", LOG_WARNING); + return -1; + } + + // Add odtgeneration hook + if (!is_object($hookmanager)) { + include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; + $hookmanager = new HookManager($this->db); + } + $hookmanager->initHooks(array('odtgeneration')); + global $action; + + if (!is_object($outputlangs)) { + $outputlangs = $langs; + } + $sav_charset_output = $outputlangs->charset_output; + $outputlangs->charset_output = 'UTF-8'; + + $outputlangs->loadLangs(array("main", "dict", "companies", "bills")); + + if ($conf->dolisirh->dir_output) { + // If $object is id instead of object + if (!is_object($object)) { + $id = $object; + $object = new TimeSheet($this->db); + $result = $object->fetch($id); + if ($result < 0) { + dol_print_error($this->db, $object->error); + return -1; + } + } + + $object->fetch_thirdparty(); + + $objectref = dol_sanitizeFileName($object->ref); + $dir = $conf->dolisirh->multidir_output[isset($object->entity) ? $object->entity : 1] . '/timesheetdocument/' . $objectref; + +// if (!preg_match('/specimen/i', $objectref)) { +// $dir .= "/".$objectref; +// } + + if (!file_exists($dir)) { + if (dol_mkdir($dir) < 0) { + $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir); + return -1; + } + } + + if (file_exists($dir)) { + //print "srctemplatepath=".$srctemplatepath; // Src filename + $newfile = basename($srctemplatepath); + $newfiletmp = preg_replace('/\.od(t|s)/i', '', $newfile); + $newfiletmp = preg_replace('/template_/i', '', $newfiletmp); + $newfiletmp = preg_replace('/modele_/i', '', $newfiletmp); + + $date = dol_print_date(dol_now(),'dayxcard'); + + $newfiletmp = $objectref . '_' . $date . '_' . $newfiletmp . '_' . $conf->global->MAIN_INFO_SOCIETE_NOM; + + // Get extension (ods or odt) + $newfileformat = substr($newfile, strrpos($newfile, '.') + 1); + if (!empty($conf->global->MAIN_DOC_USE_TIMING)) { + $format = $conf->global->MAIN_DOC_USE_TIMING; + if ($format == '1') { + $format = '%Y%m%d%H%M%S'; + } + $filename = $newfiletmp.'-'.dol_print_date(dol_now(), $format).'.'.$newfileformat; + } else { + $filename = $newfiletmp.'.'.$newfileformat; + } + $file = $dir.'/'.$filename; + //print "newdir=".$dir; + //print "newfile=".$newfile; + //print "file=".$file; + //print "conf->societe->dir_temp=".$conf->societe->dir_temp; + + dol_mkdir($conf->dolisirh->dir_temp); + if (!is_writable($conf->dolisirh->dir_temp)) { + $this->error = "Failed to write in temp directory ".$conf->dolisirh->dir_temp; + dol_syslog('Error in write_file: '.$this->error, LOG_ERR); + return -1; + } + + // If CUSTOMER contact defined on order, we use it + $usecontact = false; + $arrayidcontact = $object->getIdContact('external', 'CUSTOMER'); + if (count($arrayidcontact) > 0) { + $usecontact = true; + $result = $object->fetch_contact($arrayidcontact[0]); + } + + // Recipient name + $contactobject = null; + if (!empty($usecontact)) { + // We can use the company of contact instead of thirdparty company + if ($object->contact->socid != $object->thirdparty->id && (!isset($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT) || !empty($conf->global->MAIN_USE_COMPANY_NAME_OF_CONTACT))) { + $object->contact->fetch_thirdparty(); + $socobject = $object->contact->thirdparty; + $contactobject = $object->contact; + } else { + $socobject = $object->thirdparty; + // if we have a CUSTOMER contact and we dont use it as thirdparty recipient we store the contact object for later use + $contactobject = $object->contact; + } + } else { + $socobject = $object->thirdparty; + } + + // Make substitution + $substitutionarray = array( + '__FROM_NAME__' => $this->emetteur->name, + '__FROM_EMAIL__' => $this->emetteur->email, + '__TOTAL_TTC__' => $object->total_ttc, + '__TOTAL_HT__' => $object->total_ht, + '__TOTAL_VAT__' => $object->total_tva + ); + complete_substitutions_array($substitutionarray, $langs, $object); + // Call the ODTSubstitution hook + $parameters = array('file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs, 'substitutionarray'=>&$substitutionarray); + $reshook = $hookmanager->executeHooks('ODTSubstitution', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + + // Line of free text + $newfreetext = ''; + $paramfreetext = 'ORDER_FREE_TEXT'; + if (!empty($conf->global->$paramfreetext)) { + $newfreetext = make_substitutions($conf->global->$paramfreetext, $substitutionarray); + } + + // Open and load template + require_once ODTPHP_PATH.'odf.php'; + try { + $odfHandler = new odf( + $srctemplatepath, + array( + 'PATH_TO_TMP' => $conf->dolisirh->dir_temp, + 'ZIP_PROXY' => 'PclZipProxy', // PhpZipProxy or PclZipProxy. Got "bad compression method" error when using PhpZipProxy. + 'DELIMITER_LEFT' => '{', + 'DELIMITER_RIGHT' => '}' + ) + ); + } catch (Exception $e) { + $this->error = $e->getMessage(); + dol_syslog($e->getMessage(), LOG_INFO); + return -1; + } + // After construction $odfHandler->contentXml contains content and + // [!-- BEGIN row.lines --]*[!-- END row.lines --] has been replaced by + // [!-- BEGIN lines --]*[!-- END lines --] + //print html_entity_decode($odfHandler->__toString()); + //print exit; + + + // Make substitutions into odt of freetext + try { + $odfHandler->setVars('free_text', $newfreetext, true, 'UTF-8'); + } catch (OdfException $e) { + dol_syslog($e->getMessage(), LOG_INFO); + } + + // Define substitution array + $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $object); + $array_object_from_properties = $this->get_substitutionarray_each_var_object($object, $outputlangs); + $array_objet = $this->get_substitutionarray_object($object, $outputlangs); + $array_user = $this->get_substitutionarray_user($user, $outputlangs); + $array_soc = $this->get_substitutionarray_mysoc($mysoc, $outputlangs); + $array_soc['mycompany_logo'] = preg_replace('/_small/', '_mini', $array_soc['mycompany_logo']); + $array_thirdparty = $this->get_substitutionarray_thirdparty($socobject, $outputlangs); + $array_other = $this->get_substitutionarray_other($outputlangs); + // retrieve contact information for use in object as contact_xxx tags + $array_thirdparty_contact = array(); + if ($usecontact && is_object($contactobject)) { + $array_thirdparty_contact = $this->get_substitutionarray_contact($contactobject, $outputlangs, 'contact'); + } + + $tmparray = array_merge($substitutionarray, $array_object_from_properties, $array_user, $array_soc, $array_thirdparty, $array_objet, $array_other, $array_thirdparty_contact); + complete_substitutions_array($tmparray, $outputlangs, $object); + + // Call the ODTSubstitution hook + $parameters = array('odfHandler'=>&$odfHandler, 'file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs, 'substitutionarray'=>&$tmparray); + $reshook = $hookmanager->executeHooks('ODTSubstitution', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + + require_once DOL_DOCUMENT_ROOT.'/holiday/class/holiday.class.php'; + + $usertmp = new User($this->db); + $task = new Task($this->db); + $project = new Project($this->db); + $extrafields = new ExtraFields($this->db); + $holiday = new Holiday($this->db); + + $usertmp->fetch($object->fk_user_assign); + + $datestart = dol_getdate($object->date_start); + $firstdaytoshow = dol_get_first_day($datestart['year'], $datestart['mon']); + $firstdaytoshowgmt = dol_get_first_day($datestart['year'], $datestart['mon'], true); + $dayInMonth = cal_days_in_month(CAL_GREGORIAN, $datestart['mon'], $datestart['year']); + $daystarttoshow = $object->date_start - 12 * 60 * 60; + $daystarttoshowgmt = $object->date_start - 12 * 60 * 60; + $dayInDateRange = num_between_day($object->date_start, $object->date_end, 1); + $lastdaytoshow = $object->date_end - 12 * 60 * 60; + + for ($idw = 0; $idw < $dayInDateRange; $idw++) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($daystarttoshow, $idw, 'd'); + $day = dol_getdate($dayinloopfromfirstdaytoshow); + $dayInDateRangeArray[] = $day['mday']; + } + + $tasksarray = $task->getTasksArray(0, 0, 0, 0, 0, '', '', '', $object->fk_user_assign, 0, $extrafields); + + $isavailable = array(); + + for ($idw = 0; $idw < $dayInMonth; $idw++) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); // $daystarttoshow is a date with hours = 0 + $dayinloopfromfirstdaytoshowgmt = dol_time_plus_duree($firstdaytoshowgmt, $idw, 'd'); // $daystarttoshow is a date with hours = 0 + + $statusofholidaytocheck = Holiday::STATUS_APPROVED; + + $isavailablefordayanduser = $holiday->verifDateHolidayForTimestamp($object->fk_user_assign, $dayinloopfromfirstdaytoshow, $statusofholidaytocheck); + $isavailable[$dayinloopfromfirstdaytoshow] = $isavailablefordayanduser; // in projectLinesPerWeek later, we are using $daystarttoshow and dol_time_plus_duree to loop on each day + + $test = num_public_holiday($dayinloopfromfirstdaytoshowgmt, $dayinloopfromfirstdaytoshowgmt + 86400, $mysoc->country_code); + if ($test) { + $isavailable[$dayinloopfromfirstdaytoshow] = array('morning'=>false, 'afternoon'=>false, 'morning_reason'=>'public_holiday', 'afternoon_reason'=>'public_holiday'); + } + } + + $j = 0; + $level = 0; + $projectsrole = $task->getUserRolesForProjectsOrTasks($usertmp, 0, ($project->id ?: 0), 0, 1); + $tasksrole = $task->getUserRolesForProjectsOrTasks(0, $usertmp, ($project->id ?: 0), 0, 1); + $restrictviewformytask = ((!isset($conf->global->PROJECT_TIME_SHOW_TASK_NOT_ASSIGNED)) ? 2 : $conf->global->PROJECT_TIME_SHOW_TASK_NOT_ASSIGNED); + $totalforvisibletasks = projectLinesPerDayOnMonth($j, $daystarttoshow, $lastdaytoshow, $usertmp, 0, $tasksarray, $level, $projectsrole, $tasksrole, 0, $restrictviewformytask, $isavailable, 0, array(), $extrafields, $dayInMonth, 1); + + $tmparray['employee_firstname'] = $usertmp->firstname; + $tmparray['employee_lastname'] = $usertmp->lastname; + $tmparray['date_start'] = dol_print_date($object->date_start, 'day', 'tzuser'); + $tmparray['date_end'] = dol_print_date($object->date_end, 'day', 'tzuser'); + $tmparray['note_public'] = $object->note_public; + + $tmparray['month_year'] = dol_print_date($object->date_start, "%B %Y", 'tzuser'); + + $project->fetch($conf->global->DOLISIRH_HR_PROJECT); + + $tmparray['project_rh_ref'] = $project->ref; + $tmparray['project_rh'] = $project->title; + + $signatory = new TimeSheetSignature($this->db); + + $society_responsible = $signatory->fetchSignatory('TIMESHEET_SOCIETY_RESPONSIBLE', $object->id, 'timesheet'); + $society_responsible = is_array($society_responsible) ? array_shift($society_responsible) : $society_responsible; + $societey_attendant = $signatory->fetchSignatory('TIMESHEET_SOCIETY_ATTENDANT', $object->id, 'timesheet'); + $societey_attendant = is_array($societey_attendant) ? array_shift($societey_attendant) : $societey_attendant; + + $tempdir = $conf->dolisirh->multidir_output[isset($object->entity) ? $object->entity : 1] . '/temp/'; + + //Signatures + if ( ! empty($society_responsible) && $society_responsible > 0) { + $tmparray['society_responsible_fullname'] = $society_responsible->lastname . ' ' . $society_responsible->firstname; + $tmparray['society_responsible_signature_date'] = dol_print_date($society_responsible->signature_date, 'dayhoursec'); + + $encoded_image = explode(",", $society_responsible->signature)[1]; + $decoded_image = base64_decode($encoded_image); + file_put_contents($tempdir . "signature.png", $decoded_image); + $tmparray['society_responsible_signature'] = $tempdir . "signature.png"; + } else { + $tmparray['society_responsible_fullname'] = ''; + $tmparray['society_responsible_signature_date'] = ''; + $tmparray['society_responsible_signature'] = ''; + } + if ( ! empty($societey_attendant) && $societey_attendant > 0) { + $tmparray['society_attendant_fullname'] = $societey_attendant->lastname . ' ' . $societey_attendant->firstname; + $tmparray['society_attendant_signature_date'] = dol_print_date($societey_attendant->signature_date, 'dayhoursec'); + + $encoded_image = explode(",", $societey_attendant->signature)[1]; + $decoded_image = base64_decode($encoded_image); + file_put_contents($tempdir . "signature1.png", $decoded_image); + $tmparray['society_attendant_signature'] = $tempdir . "signature1.png"; + } else { + $tmparray['society_attendant_fullname'] = ''; + $tmparray['society_attendant_signature_date'] = ''; + $tmparray['society_attendant_signature'] = ''; + } + + unset($tmparray['object_fields']); + unset($tmparray['object_lines']); + + foreach ($tmparray as $key => $value) { + try { + if ($key == 'society_responsible_signature' || $key == 'society_attendant_signature') { // Image + if (file_exists($value)) { + $list = getimagesize($value); + $newWidth = 350; + if ($list[0]) { + $ratio = $newWidth / $list[0]; + $newHeight = $ratio * $list[1]; + dol_imageResizeOrCrop($value, 0, $newWidth, $newHeight); + } + $odfHandler->setImage($key, $value); + } else { + $odfHandler->setVars($key, $langs->trans('NoData'), true, 'UTF-8'); + } + } elseif (preg_match('/logo$/', $key)) { + if (file_exists($value)) $odfHandler->setImage($key, $value); + else $odfHandler->setVars($key, $langs->transnoentities('ErrorFileNotFound'), true, 'UTF-8'); + } elseif (empty($value)) { // Text + $odfHandler->setVars($key, $langs->trans('NoData'), true, 'UTF-8'); + } else { + $odfHandler->setVars($key, html_entity_decode($value, ENT_QUOTES | ENT_HTML5), true, 'UTF-8'); + } + } catch (OdfException $e) { + dol_syslog($e->getMessage(), LOG_INFO); + } + } + // Replace tags of lines + try { + $foundtagforlines = 1; + try { + $listlines = $odfHandler->setSegment('days'); + } catch (OdfException $e) { + // We may arrive here if tags for lines not present into template + $foundtagforlines = 0; + dol_syslog($e->getMessage(), LOG_INFO); + } + if ($foundtagforlines) { + $linenumber = 0; + for ($idw = 1; $idw <= 31; $idw++) { + if (in_array($idw, $dayInDateRangeArray)) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($daystarttoshow, array_search($idw, $dayInDateRangeArray), 'd'); // $daystarttoshow is a date with hours = 0 + $tmparray['day'.$idw] = dol_print_date($dayinloopfromfirstdaytoshow, '%a'); + } else { + $tmparray['day'.$idw] = '-'; + } + } + +// $linenumber++; +// $tmparray = $this->get_substitutionarray_lines($line, $outputlangs, $linenumber); +// complete_substitutions_array($tmparray, $outputlangs, $object, $line, "completesubstitutionarray_lines"); + + unset($tmparray['object_fields']); + unset($tmparray['object_lines']); + + // Call the ODTSubstitutionLine hook + $parameters = array('odfHandler'=>&$odfHandler, 'file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs, 'substitutionarray'=>&$tmparray, 'line'=>$line); + $reshook = $hookmanager->executeHooks('ODTSubstitutionLine', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + foreach ($tmparray as $key => $val) { + try { + $listlines->setVars($key, $val, true, 'UTF-8'); + } catch (OdfException $e) { + dol_syslog($e->getMessage(), LOG_INFO); + } catch (SegmentException $e) { + dol_syslog($e->getMessage(), LOG_INFO); + } + } + $listlines->merge(); + $odfHandler->mergeSegment($listlines); + } + + $filter = ' AND p.rowid != ' . $conf->global->DOLISIRH_HR_PROJECT; + $tasksArray = $task->getTasksArray(0, 0, 0, 0, 0, '', '', $filter, $object->fk_user_assign, 0, $extrafields); + if (is_array($tasksArray) && !empty($tasksArray)) { + foreach ($tasksArray as $tasksingle) { + $filter = ' AND ptt.fk_task = ' . $tasksingle->id . ' AND ptt.task_date BETWEEN ' . "'" .dol_print_date($object->date_start, 'dayrfc') . "'" . ' AND ' . "'" . dol_print_date($object->date_end, 'dayrfc'). "'"; + $alltimespent = $task->fetchAllTimeSpent($usertmp, $filter); + $totaltimespent = 0; + if (is_array($alltimespent) && !empty($alltimespent)) { + foreach ($alltimespent as $timespent) { + $totaltimespent += $timespent->timespent_duration; + } + } + if ($totaltimespent > 0) { + $foundtagforlines = 1; + try { + $listlines = $odfHandler->setSegment('times'); + } catch (OdfException $e) { + // We may arrive here if tags for lines not present into template + $foundtagforlines = 0; + dol_syslog($e->getMessage(), LOG_INFO); + } + if ($foundtagforlines) { + $linenumber = 0; + + $project->fetch($tasksingle->fk_project); + + loadTimeSpentMonthByDay($daystarttoshow, $lastdaytoshow, $tasksingle->id, $object->fk_user_assign, $project); + + for ($idw = 1; $idw <= 31; $idw++) { + $tmparray['task_ref'] = $tasksingle->ref; + $tmparray['task_label'] = dol_trunc($tasksingle->label, 16); + if (in_array($idw, $dayInDateRangeArray)) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($daystarttoshow, array_search($idw, $dayInDateRangeArray), 'd'); // $daystarttoshow is a date with hours = 0 + $tmparray['time' . $idw] = (($project->monthWorkLoadPerTask[$dayinloopfromfirstdaytoshow][$tasksingle->id] != 0) ? convertSecondToTime($project->monthWorkLoadPerTask[$dayinloopfromfirstdaytoshow][$tasksingle->id], (is_float($project->monthWorkLoadPerTask[$dayinloopfromfirstdaytoshow][$tasksingle->id] / 60 / 60) ? 'allhourmin' : 'allhour')) : '-'); + } else { + $tmparray['time' . $idw] = '-'; + } + } + +// $linenumber++; +// $tmparray = $this->get_substitutionarray_lines($line, $outputlangs, $linenumber); +// complete_substitutions_array($tmparray, $outputlangs, $object, $line, "completesubstitutionarray_lines"); + + unset($tmparray['object_fields']); + unset($tmparray['object_lines']); + + // Call the ODTSubstitutionLine hook + $parameters = array('odfHandler' => &$odfHandler, 'file' => $file, 'object' => $object, 'outputlangs' => $outputlangs, 'substitutionarray' => &$tmparray, 'line' => $line); + $reshook = $hookmanager->executeHooks('ODTSubstitutionLine', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + foreach ($tmparray as $key => $val) { + try { + if (empty($val)) { + $listlines->setVars($key, $langs->trans('NoData'), true, 'UTF-8'); + } else { + $listlines->setVars($key, html_entity_decode($val, ENT_QUOTES | ENT_HTML5), true, 'UTF-8'); + } + } catch (OdfException $e) { + dol_syslog($e->getMessage(), LOG_INFO); + } catch (SegmentException $e) { + dol_syslog($e->getMessage(), LOG_INFO); + } + } + $listlines->merge(); + } + } + } + $odfHandler->mergeSegment($listlines); + } + + $project->fetch($conf->global->DOLISIRH_HR_PROJECT); + $tasksArray = $task->getTasksArray(0, 0, $conf->global->DOLISIRH_HR_PROJECT, 0, 0, '', '', '', $object->fk_user_assign, 0, $extrafields); + $segment = array( + array( + 'csss', + 'cps', + 'rtts', + 'jfs', + 'cms', + ), + array( + 'css', + 'cp', + 'rtt', + 'jf', + 'cm', + ) + ); + $i = 0; + if (is_array($tasksArray) && !empty($tasksArray)) { + foreach ($tasksArray as $tasksingle) { + $foundtagforlines = 1; + try { + $listlines = $odfHandler->setSegment($segment[0][$i]); + } catch (OdfException $e) { + // We may arrive here if tags for lines not present into template + $foundtagforlines = 0; + dol_syslog($e->getMessage(), LOG_INFO); + } + if ($foundtagforlines) { + $linenumber = 0; + + loadTimeSpentMonthByDay($daystarttoshow, $lastdaytoshow, $tasksingle->id, $object->fk_user_assign, $project); + + //echo '
'; print_r($project->monthWorkLoad); echo '
'; + + for ($idw = 1; $idw <= 31; $idw++) { + if (in_array($idw, $dayInDateRangeArray)) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($daystarttoshow, array_search($idw, $dayInDateRangeArray), 'd'); // $daystarttoshow is a date with hours = 0 + $tmparray[$segment[1][$i] . $idw] = (($project->monthWorkLoadPerTask[$dayinloopfromfirstdaytoshow][$tasksingle->id] != 0) ? convertSecondToTime($project->monthWorkLoadPerTask[$dayinloopfromfirstdaytoshow][$tasksingle->id], (is_float($project->monthWorkLoadPerTask[$dayinloopfromfirstdaytoshow][$tasksingle->id] / 60 / 60) ? 'allhourmin' : 'allhour')) : '-'); + } else { + $tmparray[$segment[1][$i] . $idw] = '-'; + } + } + +// $linenumber++; +// $tmparray = $this->get_substitutionarray_lines($line, $outputlangs, $linenumber); +// complete_substitutions_array($tmparray, $outputlangs, $object, $line, "completesubstitutionarray_lines"); + + unset($tmparray['object_fields']); + unset($tmparray['object_lines']); + + // Call the ODTSubstitutionLine hook + $parameters = array('odfHandler'=>&$odfHandler, 'file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs, 'substitutionarray'=>&$tmparray, 'line'=>$line); + $reshook = $hookmanager->executeHooks('ODTSubstitutionLine', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + foreach ($tmparray as $key => $val) { + try { + $listlines->setVars($key, $val, true, 'UTF-8'); + } catch (OdfException $e) { + dol_syslog($e->getMessage(), LOG_INFO); + } catch (SegmentException $e) { + dol_syslog($e->getMessage(), LOG_INFO); + } + } + $listlines->merge(); + $odfHandler->mergeSegment($listlines); + } + $i++; + } + } + + // Total time RH + $foundtagforlines = 1; + try { + $listlines = $odfHandler->setSegment('totalrhs'); + } catch (OdfException $e) { + // We may arrive here if tags for lines not present into template + $foundtagforlines = 0; + dol_syslog($e->getMessage(), LOG_INFO); + } + if ($foundtagforlines) { + $linenumber = 0; + for ($idw = 1; $idw <= 31; $idw++) { + if (in_array($idw, $dayInDateRangeArray)) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($daystarttoshow, array_search($idw, $dayInDateRangeArray), 'd'); // $daystarttoshow is a date with hours = 0 + $tmparray['totalrh' . $idw] = (($project->monthWorkLoad[$dayinloopfromfirstdaytoshow] != 0) ? convertSecondToTime($project->monthWorkLoad[$dayinloopfromfirstdaytoshow], (is_float($project->monthWorkLoad[$dayinloopfromfirstdaytoshow] / 60 / 60) ? 'allhourmin' : 'allhour')) : '-'); + } else { + $tmparray['totalrh' . $idw] = '-'; + } + } + +// $linenumber++; +// $tmparray = $this->get_substitutionarray_lines($line, $outputlangs, $linenumber); +// complete_substitutions_array($tmparray, $outputlangs, $object, $line, "completesubstitutionarray_lines"); + + unset($tmparray['object_fields']); + unset($tmparray['object_lines']); + + // Call the ODTSubstitutionLine hook + $parameters = array('odfHandler'=>&$odfHandler, 'file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs, 'substitutionarray'=>&$tmparray, 'line'=>$line); + $reshook = $hookmanager->executeHooks('ODTSubstitutionLine', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + foreach ($tmparray as $key => $val) { + try { + $listlines->setVars($key, $val, true, 'UTF-8'); + } catch (OdfException $e) { + dol_syslog($e->getMessage(), LOG_INFO); + } catch (SegmentException $e) { + dol_syslog($e->getMessage(), LOG_INFO); + } + } + $listlines->merge(); + $odfHandler->mergeSegment($listlines); + } + + // Total time consumed whithout Project RH + $foundtagforlines = 1; + try { + $listlines = $odfHandler->setSegment('totaltimes'); + } catch (OdfException $e) { + // We may arrive here if tags for lines not present into template + $foundtagforlines = 0; + dol_syslog($e->getMessage(), LOG_INFO); + } + if ($foundtagforlines) { + $linenumber = 0; + + for ($idw = 1; $idw <= 31; $idw++) { + if (in_array($idw, $dayInDateRangeArray)) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($daystarttoshow, array_search($idw, $dayInDateRangeArray), 'd'); // $daystarttoshow is a date with hours = 0 + $totaltime = $totalforvisibletasks[$dayinloopfromfirstdaytoshow] - $project->monthWorkLoad[$dayinloopfromfirstdaytoshow]; + $tmparray['totaltime' . $idw] = (($totaltime != 0) ? convertSecondToTime($totaltime, (is_float($totaltime / 60 / 60) ? 'allhourmin' : 'allhour')) : '-'); + } else { + $tmparray['totaltime' . $idw] = '-'; + } + } + +// $linenumber++; +// $tmparray = $this->get_substitutionarray_lines($line, $outputlangs, $linenumber); +// complete_substitutions_array($tmparray, $outputlangs, $object, $line, "completesubstitutionarray_lines"); + + unset($tmparray['object_fields']); + unset($tmparray['object_lines']); + + // Call the ODTSubstitutionLine hook + $parameters = array('odfHandler'=>&$odfHandler, 'file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs, 'substitutionarray'=>&$tmparray, 'line'=>$line); + $reshook = $hookmanager->executeHooks('ODTSubstitutionLine', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + foreach ($tmparray as $key => $val) { + try { + $listlines->setVars($key, $val, true, 'UTF-8'); + } catch (OdfException $e) { + dol_syslog($e->getMessage(), LOG_INFO); + } catch (SegmentException $e) { + dol_syslog($e->getMessage(), LOG_INFO); + } + } + $listlines->merge(); + $odfHandler->mergeSegment($listlines); + } + + // Total time consumed + $foundtagforlines = 1; + try { + $listlines = $odfHandler->setSegment('totaltpss'); + } catch (OdfException $e) { + // We may arrive here if tags for lines not present into template + $foundtagforlines = 0; + dol_syslog($e->getMessage(), LOG_INFO); + } + if ($foundtagforlines) { + $linenumber = 0; + for ($idw = 1; $idw <= 31; $idw++) { + if (in_array($idw, $dayInDateRangeArray)) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($daystarttoshow, array_search($idw, $dayInDateRangeArray), 'd'); // $daystarttoshow is a date with hours = 0 + $tmparray['totaltps' . $idw] = (($totalforvisibletasks[$dayinloopfromfirstdaytoshow] != 0) ? convertSecondToTime($totalforvisibletasks[$dayinloopfromfirstdaytoshow], (is_float($totalforvisibletasks[$dayinloopfromfirstdaytoshow] / 60 / 60) ? 'allhourmin' : 'allhour')) : '-'); + } else { + $tmparray['totaltps' . $idw] = '-'; + } + } + +// $linenumber++; +// $tmparray = $this->get_substitutionarray_lines($line, $outputlangs, $linenumber); +// complete_substitutions_array($tmparray, $outputlangs, $object, $line, "completesubstitutionarray_lines"); + + unset($tmparray['object_fields']); + unset($tmparray['object_lines']); + + // Call the ODTSubstitutionLine hook + $parameters = array('odfHandler'=>&$odfHandler, 'file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs, 'substitutionarray'=>&$tmparray, 'line'=>$line); + $reshook = $hookmanager->executeHooks('ODTSubstitutionLine', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + foreach ($tmparray as $key => $val) { + try { + $listlines->setVars($key, $val, true, 'UTF-8'); + } catch (OdfException $e) { + dol_syslog($e->getMessage(), LOG_INFO); + } catch (SegmentException $e) { + dol_syslog($e->getMessage(), LOG_INFO); + } + } + $listlines->merge(); + $odfHandler->mergeSegment($listlines); + } + + // Total time spent + $foundtagforlines = 1; + try { + $listlines = $odfHandler->setSegment('tas'); + } catch (OdfException $e) { + // We may arrive here if tags for lines not present into template + $foundtagforlines = 0; + dol_syslog($e->getMessage(), LOG_INFO); + } + if ($foundtagforlines) { + $linenumber = 0; + + $workinghours = new Workinghours($this->db); + $workinghoursArray = $workinghours->fetchCurrentWorkingHours($object->fk_user_assign, 'user'); + $workinghoursMonth = 0; + + for ($idw = 1; $idw <= 31; $idw++) { + if (in_array($idw, $dayInDateRangeArray)) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($daystarttoshow, array_search($idw, $dayInDateRangeArray), 'd'); // $daystarttoshow is a date with hours = 0 + if ($isavailable[$dayinloopfromfirstdaytoshow]['morning'] && $isavailable[$dayinloopfromfirstdaytoshow]['afternoon']) { + $currentDay = date('l', $dayinloopfromfirstdaytoshow); + $currentDay = 'workinghours_' . strtolower($currentDay); + $workinghoursMonth = $workinghoursArray->{$currentDay} * 60; + } else { + $workinghoursMonth = 0; + } + $tmparray['ta' . $idw] = (($workinghoursMonth != 0) ? convertSecondToTime($workinghoursMonth, (is_float($workinghoursMonth / 60 / 60) ? 'allhourmin' : 'allhour')) : '-'); + } else { + $tmparray['ta' . $idw] = '-'; + } + } + +// $linenumber++; +// $tmparray = $this->get_substitutionarray_lines($line, $outputlangs, $linenumber); +// complete_substitutions_array($tmparray, $outputlangs, $object, $line, "completesubstitutionarray_lines"); + + unset($tmparray['object_fields']); + unset($tmparray['object_lines']); + + // Call the ODTSubstitutionLine hook + $parameters = array('odfHandler'=>&$odfHandler, 'file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs, 'substitutionarray'=>&$tmparray, 'line'=>$line); + $reshook = $hookmanager->executeHooks('ODTSubstitutionLine', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + foreach ($tmparray as $key => $val) { + try { + $listlines->setVars($key, $val, true, 'UTF-8'); + } catch (OdfException $e) { + dol_syslog($e->getMessage(), LOG_INFO); + } catch (SegmentException $e) { + dol_syslog($e->getMessage(), LOG_INFO); + } + } + $listlines->merge(); + $odfHandler->mergeSegment($listlines); + } + + // Diff between time consumed and time spent + $foundtagforlines = 1; + try { + $listlines = $odfHandler->setSegment('diffs'); + } catch (OdfException $e) { + // We may arrive here if tags for lines not present into template + $foundtagforlines = 0; + dol_syslog($e->getMessage(), LOG_INFO); + } + if ($foundtagforlines) { + $linenumber = 0; + + $workinghours = new Workinghours($this->db); + $workinghoursArray = $workinghours->fetchCurrentWorkingHours($object->fk_user_assign, 'user'); + $workinghoursMonth = 0; + + for ($idw = 1; $idw <= 31; $idw++) { + if (in_array($idw, $dayInDateRangeArray)) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($daystarttoshow, array_search($idw, $dayInDateRangeArray), 'd'); // $daystarttoshow is a date with hours = 0 + if ($isavailable[$dayinloopfromfirstdaytoshow]['morning'] && $isavailable[$dayinloopfromfirstdaytoshow]['afternoon']) { + $currentDay = date('l', $dayinloopfromfirstdaytoshow); + $currentDay = 'workinghours_' . strtolower($currentDay); + $workinghoursMonth = $workinghoursArray->{$currentDay} * 60; + } else { + $workinghoursMonth = 0; + } + $difftotaltime = $workinghoursMonth - $totalforvisibletasks[$dayinloopfromfirstdaytoshow]; + $tmparray['diff' . $idw] = (($difftotaltime != 0) ? convertSecondToTime(abs($difftotaltime), (is_float($difftotaltime / 60 / 60) ? 'allhourmin' : 'allhour')) : '-'); + } else { + $tmparray['diff' . $idw] = '-'; + } + } + +// $linenumber++; +// $tmparray = $this->get_substitutionarray_lines($line, $outputlangs, $linenumber); +// complete_substitutions_array($tmparray, $outputlangs, $object, $line, "completesubstitutionarray_lines"); + + unset($tmparray['object_fields']); + unset($tmparray['object_lines']); + + // Call the ODTSubstitutionLine hook + $parameters = array('odfHandler'=>&$odfHandler, 'file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs, 'substitutionarray'=>&$tmparray, 'line'=>$line); + $reshook = $hookmanager->executeHooks('ODTSubstitutionLine', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + + foreach ($tmparray as $key => $val) { + try { + $listlines->setVars($key, $val, true, 'UTF-8'); + } catch (OdfException $e) { + dol_syslog($e->getMessage(), LOG_INFO); + } catch (SegmentException $e) { + dol_syslog($e->getMessage(), LOG_INFO); + } + } + $listlines->merge(); + $odfHandler->mergeSegment($listlines); + } + + // TimeSheetDet + $foundtagforlines = 1; + try { + $listlines = $odfHandler->setSegment('timesheetdet'); + } catch (OdfException $e) { + // We may arrive here if tags for lines not present into template + $foundtagforlines = 0; + dol_syslog($e->getMessage(), LOG_INFO); + } + if ($foundtagforlines) { + $linenumber = 0; + + $object->fetchLines(); + if (is_array($object->lines) && !empty($object->lines)) { + foreach ($object->lines as $line) { + if ($line->fk_product > 0) { + $product = new Product($this->db); + $product->fetch($line->fk_product); + $tmparray['timesheetdet_label'] = $product->label; + $tmparray['timesheetdet_qty'] = $line->qty; + } elseif (!empty($line->description)) { + $tmparray['timesheetdet_label'] = $line->description; + $tmparray['timesheetdet_qty'] = $line->qty; + } + //$linenumber++; + //$tmparray = $this->get_substitutionarray_lines($line, $outputlangs, $linenumber); + //complete_substitutions_array($tmparray, $outputlangs, $object, $line, "completesubstitutionarray_lines"); + + unset($tmparray['object_fields']); + unset($tmparray['object_lines']); + + // Call the ODTSubstitutionLine hook + $parameters = array('odfHandler' => &$odfHandler, 'file' => $file, 'object' => $object, 'outputlangs' => $outputlangs, 'substitutionarray' => &$tmparray, 'line' => $line); + $reshook = $hookmanager->executeHooks('ODTSubstitutionLine', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + + foreach ($tmparray as $key => $val) { + try { + $listlines->setVars($key, $val, true, 'UTF-8'); + } catch (OdfException $e) { + dol_syslog($e->getMessage(), LOG_INFO); + } catch (SegmentException $e) { + dol_syslog($e->getMessage(), LOG_INFO); + } + } + $listlines->merge(); + } + } + $odfHandler->mergeSegment($listlines); + } + + } catch (OdfException $e) { + $this->error = $e->getMessage(); + dol_syslog($this->error, LOG_WARNING); + return -1; + } + + // Replace labels translated + $tmparray = $outputlangs->get_translations_for_substitutions(); + foreach ($tmparray as $key => $value) { + try { + $odfHandler->setVars($key, $value, true, 'UTF-8'); + } catch (OdfException $e) { + dol_syslog($e->getMessage(), LOG_INFO); + } + } + + // Call the beforeODTSave hook + + $parameters = array('odfHandler'=>&$odfHandler, 'file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs, 'substitutionarray'=>&$tmparray); + $reshook = $hookmanager->executeHooks('beforeODTSave', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + + // Write new file + if (!empty($conf->global->MAIN_ODT_AS_PDF)) { + try { + $odfHandler->exportAsAttachedPDF($file); + } catch (Exception $e) { + $this->error = $e->getMessage(); + dol_syslog($e->getMessage(), LOG_INFO); + return -1; + } + } else { + try { + $odfHandler->saveToDisk($file); + } catch (Exception $e) { + $this->error = $e->getMessage(); + dol_syslog($e->getMessage(), LOG_INFO); + return -1; + } + } + + $parameters = array('odfHandler'=>&$odfHandler, 'file'=>$file, 'object'=>$object, 'outputlangs'=>$outputlangs, 'substitutionarray'=>&$tmparray); + $reshook = $hookmanager->executeHooks('afterODTCreation', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks + + if (!empty($conf->global->MAIN_UMASK)) { + @chmod($file, octdec($conf->global->MAIN_UMASK)); + } + + $odfHandler = null; // Destroy object + + dol_delete_file($tempdir . "signature.png"); + dol_delete_file($tempdir . "signature1.png"); + + $this->result = array('fullpath'=>$file); + + return 1; // Success + } else { + $this->error = $langs->transnoentities("ErrorCanNotCreateDir", $dir); + return -1; + } + } + + return -1; + } +} diff --git a/core/modules/dolisirh/timesheetdocument/index.php b/core/modules/dolisirh/timesheetdocument/index.php new file mode 100644 index 0000000..17927e6 --- /dev/null +++ b/core/modules/dolisirh/timesheetdocument/index.php @@ -0,0 +1,2 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * or see https://www.gnu.org/ + */ + +/** + * \file core/modules/dolisirh/mod_timesheetdocument_standard.php + * \ingroup dolisirh + * \brief File of class to manage TimeSheetDocument numbering rules standard + */ + +/** + * Class to manage customer order numbering rules standard + */ +class mod_timesheetdocument_standard +{ + /** + * Dolibarr version of the loaded document + * @var string + */ + public $version = 'dolibarr'; // 'development', 'experimental', 'dolibarr' + + /** + * @var string document prefix + */ + public $prefix = 'TSD'; + + /** + * @var string Error code (or message) + */ + public $error = ''; + + /** + * @var string name + */ + public $name = 'Égéon'; + + /** + * Return description of numbering module + * + * @return string Text with description + */ + public function info(): string + { + global $langs; + $langs->load("dolisirh@dolisirh"); + return $langs->trans("DoliSIRHTimeSheetDocumentStandardModel", $this->prefix); + } + + /** + * Return if a module can be used or not + * + * @return boolean true if module can be used + */ + public function isEnabled(): bool + { + return true; + } + + /** + * Return an example of numbering + * + * @return string Example + */ + public function getExample(): string + { + return $this->prefix."0501-0001"; + } + + /** + * Checks if the numbers already in the database do not + * cause conflicts that would prevent this numbering working. + * + * @param Object $object Object we need next value for + * @return boolean false if are conflict, true if ok + */ + public function canBeActivated(object $object): bool + { + global $conf, $langs, $db; + + $coyymm = ''; $max = ''; + + $posindice = strlen($this->prefix) + 6; + $sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max"; + $sql .= " FROM ".MAIN_DB_PREFIX."dolisirh_documents"; + $sql .= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'"; + if ($object->ismultientitymanaged == 1) { + $sql .= " AND entity = ".$conf->entity; + } elseif ($object->ismultientitymanaged == 2) { + // TODO + } + + $resql = $db->query($sql); + if ($resql) { + $row = $db->fetch_row($resql); + if ($row) { + $coyymm = substr($row[0], 0, 6); $max = $row[0]; + } + } + if ($coyymm && !preg_match('/'.$this->prefix.'[0-9][0-9][0-9][0-9]/i', $coyymm)) { + $langs->load("errors"); + $this->error = $langs->trans('ErrorNumRefModel', $max); + return false; + } + + return true; + } + + /** + * Return next free value + * + * @param Object $object Object we need next value for + * @return string Value if KO, <0 if KO + * @throws Exception + */ + public function getNextValue(object $object) + { + global $db, $conf; + + // first we get the max value + $posindice = strlen($this->prefix) + 6; + $sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max"; + $sql .= " FROM ".MAIN_DB_PREFIX."dolisirh_documents"; + $sql .= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'"; + if ($object->ismultientitymanaged == 1) { + $sql .= " AND entity = ".$conf->entity; + } elseif ($object->ismultientitymanaged == 2) { + // TODO + } + + $resql = $db->query($sql); + if ($resql) { + $obj = $db->fetch_object($resql); + if ($obj) { + $max = intval($obj->max); + } else { + $max = 0; + } + } else { + dol_syslog("mod_timesheetdocument_standard::getNextValue", LOG_DEBUG); + return -1; + } + + //$date=time(); + $date = $object->date_creation; + $yymm = strftime("%y%m", $date); + + if ($max >= (pow(10, 4) - 1)) { + $num = $max + 1; // If counter > 9999, we do not format on 4 chars, we take number as it is + } else { + $num = sprintf("%04s", $max + 1); + } + + dol_syslog("mod_timesheetdocument_standard::getNextValue return ".$this->prefix.$yymm."-".$num); + return $this->prefix.$yymm."-".$num; + } + + /** + * Returns version of numbering module + * + * @return string Value + */ + public function getVersion(): string + { + global $langs; + $langs->load("admin"); + + if ($this->version == 'development') { + return $langs->trans("VersionDevelopment"); + } + if ($this->version == 'experimental') { + return $langs->trans("VersionExperimental"); + } + if ($this->version == 'dolibarr') { + return DOL_VERSION; + } + if ($this->version) { + return $this->version; + } + return $langs->trans("NotAvailable"); + } +} diff --git a/core/modules/dolisirh/timesheetdocument/modules_timesheetdocument.php b/core/modules/dolisirh/timesheetdocument/modules_timesheetdocument.php new file mode 100644 index 0000000..faf44bc --- /dev/null +++ b/core/modules/dolisirh/timesheetdocument/modules_timesheetdocument.php @@ -0,0 +1,47 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * or see https://www.gnu.org/ + */ + +/** + * \file core/modules/dolisirh/modules_timesheetdocument.php + * \ingroup dolisirh + * \brief File that contains parent class for timesheet document models and parent class for timesheet numbering models + */ + +require_once DOL_DOCUMENT_ROOT.'/core/class/commondocgenerator.class.php'; + +/** + * Parent class for documents models + */ +abstract class ModeleODTTimeSheetDocument extends CommonDocGenerator +{ + /** + * Return list of active generation modules + * + * @param DoliDB $db Database handler + * @param integer $maxfilenamelength Max length of value to show + * @return array List of templates + */ + public static function liste_modeles(DoliDB $db, int $maxfilenamelength = 0): array + { + $type = 'timesheetdocument'; + $list = array(); + + require_once __DIR__ . '/../../../../lib/dolisirh_function.lib.php'; + return getListOfModelsDoliSIRH($db, $type, $maxfilenamelength); + } +} diff --git a/core/modules/index.php b/core/modules/index.php new file mode 100644 index 0000000..17927e6 --- /dev/null +++ b/core/modules/index.php @@ -0,0 +1,2 @@ + + * Copyright (C) 2018-2019 Nicolas ZABOURI + * Copyright (C) 2019-2020 Frédéric France + * Copyright (C) 2020 SuperAdmin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \defgroup dolisirh Module Dolisirh + * \brief Dolisirh module descriptor. + * + * \file htdocs/dolisirh/core/modules/modDolisirh.class.php + * \ingroup dolisirh + * \brief Description and activation file for module Dolisirh + */ +include_once DOL_DOCUMENT_ROOT.'/core/modules/DolibarrModules.class.php'; + +/** + * Description and activation class for module Dolisirh + */ +class modDolisirh extends DolibarrModules +{ + /** + * Constructor. Define names, constants, directories, boxes, permissions + * + * @param DoliDB $db Database handler + */ + public function __construct($db) + { + global $langs, $conf; + $this->db = $db; + + $this->numero = 436370; // TODO Go on page https://wiki.dolibarr.org/index.php/List_of_modules_id to reserve an id number for your module + $this->rights_class = 'dolisirh'; + $this->family = "other"; + $this->module_position = '90'; + $this->name = preg_replace('/^mod/i', '', get_class($this)); + $this->description = "DolisirhDescription"; + $this->descriptionlong = "Dolisirh description (Long)"; + $this->editor_name = 'Eoxia'; + $this->editor_url = 'https://eoxia.com'; + $this->version = '1.3.0'; + $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); + $this->picto = 'dolisirh256px@dolisirh'; + + $this->module_parts = array( + 'triggers' => 1, + 'login' => 0, + 'substitutions' => 0, + 'menus' => 0, + 'tpl' => 0, + 'barcode' => 0, + 'models' => 1, + 'theme' => 0, + 'css' => array(), + 'js' => array(), + 'hooks' => array( + 'data' => array( + 'invoicecard', + 'ticketcard', + 'projecttaskcard', + 'projecttaskscard', + 'tasklist', + 'category', + 'categoryindex', + 'invoicereccard', + 'cron', + 'cronjoblist', + 'projecttasktime', + 'timesheetcard' + ), + ), + 'moduleforexternal' => 0, + ); + + $this->dirs = array("/dolisirh/temp"); + $this->config_page_url = array("setup.php@dolisirh"); + $this->hidden = false; + $this->depends = array('modProjet', 'modBookmark', 'modHoliday', 'modFckeditor', 'modSalaries', 'modProduct', 'modService', 'modSociete'); + $this->requiredby = array(); // List of module class names as string to disable if this one is disabled. Example: array('modModuleToDisable1', ...) + $this->conflictwith = array(); // List of module class names as string this module is in conflict with. Example: array('modModuleToDisable1', ...) + $this->langfiles = array("dolisirh@dolisirh"); + $this->phpmin = array(5, 5); // Minimum version of PHP required by module + $this->need_dolibarr_version = array(11, -3); // Minimum version of Dolibarr required by module + $this->warnings_activation = array(); // Warning to show when we activate module. array('always'='text') or array('FR'='textfr','ES'='textes'...) + $this->warnings_activation_ext = array(); // Warning to show when we activate an external module. array('always'='text') or array('FR'='textfr','ES'='textes'...) + $this->const = array(); + + $this->const = array( + // CONST CONFIGURATION + 1 => array('DOLISIRH_DEFAUT_TICKET_TIME', 'chaine', '15', 'Default Time', 0, 'current'), + 2 => array('DOLISIRH_SHOW_ONLY_FAVORITE_TASKS', 'integer', 1, '', 0, 'current'), + 3 => array('DOLISIRH_HR_PROJECT', 'integer', 0, '', 0, 'current'), + 4 => array('DOLISIRH_TIMESPENT_BOOKMARK_SET', 'integer', 0, '', 0, 'current'), + 5 => array('DOLISIRH_EXCEEDED_TIME_SPENT_COLOR', 'chaine', '#FF0000', '', 0, 'current'), + 6 => array('DOLISIRH_NOT_EXCEEDED_TIME_SPENT_COLOR', 'chaine', '#FFA500', '', 0, 'current'), + 7 => array('DOLISIRH_PERFECT_TIME_SPENT_COLOR', 'chaine', '#008000', '', 0, 'current'), + 8 => array('DOLISIRH_PRODUCT_SERVICE_SET', 'integer', 0, '', 0, 'current'), + + // CONST TIME SHEET + 10 => array('MAIN_AGENDA_ACTIONAUTO_TIMESHEET_CREATE', 'integer', 1, '', 0, 'current'), + 11 => array('MAIN_AGENDA_ACTIONAUTO_TIMESHEET_EDIT', 'integer', 1, '', 0, 'current'), + 12 => array('DOLISIRH_TIMESHEET_ADDON', 'chaine', 'mod_timesheet_standard', '', 0, 'current'), + 13 => array('DOLISIRH_TIMESHEET_PREFILL_DATE', 'integer', 1, '', 0, 'current'), + 14 => array('DOLISIRH_TIMESHEET_ADD_ATTENDANTS', 'integer', 0, '', 0, 'current'), + 15 => array('DOLISIRH_TIMESHEET_CHECK_DATE_END', 'integer', 1, '', 0, 'current'), + + // CONST TIMESHEET DOCUMENT + 20 => array('MAIN_AGENDA_ACTIONAUTO_TIMESHEETDOCUMENT_CREATE', 'integer', 1, '', 0, 'current'), + 21 => array('DOLISIRH_TIMESHEETDOCUMENT_ADDON', 'chaine', 'mod_timesheetdocument_standard', '', 0, 'current'), + 22 => array('DOLISIRH_TIMESHEETDOCUMENT_ADDON_ODT_PATH', 'chaine', 'DOL_DOCUMENT_ROOT/custom/dolisirh/documents/doctemplates/timesheetdocument/', '', 0, 'current'), + 23 => array('DOLISIRH_TIMESHEETDOCUMENT_CUSTOM_ADDON_ODT_PATH', 'chaine', 'DOL_DATA_ROOT/ecm/dolisirh/timesheetdocument/', '', 0, 'current'), + 24 => array('DOLISIRH_TIMESHEETDOCUMENT_DEFAULT_MODEL', 'chaine', 'timesheetdocument_odt', '', 0, 'current'), + ); + + if (!isset($conf->dolisirh) || !isset($conf->dolisirh->enabled)) { + $conf->dolisirh = new stdClass(); + $conf->dolisirh->enabled = 0; + } + + $this->tabs = array(); + $this->tabs[] = array('data' => 'user:+workinghours:Horaires:dolisirh@dolisirh:1:/custom/dolisirh/view/workinghours_card.php?id=__ID__'); // To add a new tab identified by code tabname1 + + $this->dictionaries = array(); + $this->boxes = array(); + $this->cronjobs = array(); + + // Permissions provided by this module + $this->rights = array(); + $r = 0; + + /* DOLISIRH PERMISSIONS */ + $this->rights[$r][0] = $this->numero . sprintf("%02d", $r + 1); + $this->rights[$r][1] = $langs->trans('LireDoliSIRH'); + $this->rights[$r][4] = 'read'; + $r++; + $this->rights[$r][0] = $this->numero . sprintf("%02d", $r + 1); + $this->rights[$r][1] = $langs->trans('ReadDoliSIRH'); + $this->rights[$r][4] = 'lire'; + $r++; + + /* TIMESHEET PERMISSIONS */ + $this->rights[$r][0] = $this->numero . sprintf("%02d", $r + 1); + $this->rights[$r][1] = $langs->trans('ReadTimeSheet'); + $this->rights[$r][4] = 'timesheet'; + $this->rights[$r][5] = 'read'; + $r++; + $this->rights[$r][0] = $this->numero . sprintf("%02d", $r + 1); + $this->rights[$r][1] = $langs->transnoentities('CreateTimeSheet'); + $this->rights[$r][4] = 'timesheet'; + $this->rights[$r][5] = 'write'; + $r++; + $this->rights[$r][0] = $this->numero . sprintf("%02d", $r + 1); + $this->rights[$r][1] = $langs->trans('DeleteTimeSheet'); + $this->rights[$r][4] = 'timesheet'; + $this->rights[$r][5] = 'delete'; + $r++; + + /* ADMINPAGE PANEL ACCESS PERMISSIONS */ + $this->rights[$r][0] = $this->numero . sprintf("%02d", $r + 1); + $this->rights[$r][1] = $langs->transnoentities('ReadAdminPage'); + $this->rights[$r][4] = 'adminpage'; + $this->rights[$r][5] = 'read'; + + // Main menu entries to add + $this->menu = array(); + + $langs->load('dolisirh@dolisirh'); + // Add here entries to declare new menus + /* BEGIN MODULEBUILDER TOPMENU */ + $pictopath = dol_buildpath('/custom/dolisirh/img/dolisirh32px.png', 1); + $pictoDoliSIRH = img_picto('', $pictopath, '', 1, 0, 0, '', 'pictoDoliSIRH'); + + $r = 0; + $this->menu[$r++] = array( + 'fk_menu' => 'fk_mainmenu=project,fk_leftmenu=timespent', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'type' => 'left', // This is a Top menu entry + 'titre' => 'DoliSIRHTimeSpent', + 'prefix' => $pictoDoliSIRH, + 'mainmenu' => 'project', + 'leftmenu' => 'dolisirh_timespent_list', + 'url' => '/dolisirh/view/timespent_list.php', + 'langs' => 'dolisirh@dolisirh', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position' => 1000 + $r, + 'enabled' => '$conf->dolisirh->enabled', // Define condition to show or hide menu entry. Use '$conf->dolisirh->enabled' if entry must be visible if module is enabled. + 'perms' => '1', // Use 'perms'=>'$user->rights->dolisirh->myobject->read' if you want your menu with a permission rules + 'target' => '', + 'user' => 2, // 0=Menu for internal users, 1=external users, 2=both + ); + + $this->menu[$r++] = array( + 'fk_menu' =>'fk_mainmenu=project,fk_leftmenu=timespent', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'type' => 'left', // This is a Top menu entry + 'titre' => $langs->trans('AddTimeSpent'), + 'prefix' => $pictoDoliSIRH, + 'mainmenu' => 'project', + 'leftmenu' => 'timespent', + 'url' => '/dolisirh/view/timespent_day.php', + 'langs' => 'dolisirh@dolisirh', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position' => 48520 + $r, + 'enabled' => '$conf->dolisirh->enabled', // Define condition to show or hide menu entry. Use '$conf->dolisirh->enabled' if entry must be visible if module is enabled. + 'perms' => '$user->rights->dolisirh->lire', // Use 'perms'=>'$user->rights->dolisirh->digiriskconst->read' if you want your menu with a permission rules + 'target' => '', + 'user' => 2, // 0=Menu for internal users, 1=external users, 2=both + ); + + $this->menu[$r++] = array( + 'fk_menu' => 'fk_mainmenu=hrm,fk_leftmenu=timespent', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'type' => 'left', // This is a Top menu entry + 'titre' => 'DolisirhTimeSpent', + 'prefix' => $pictoDoliSIRH, + 'mainmenu' => 'hrm', + 'leftmenu' => 'dolisirh_timespent_list', + 'url' => '/dolisirh/view/timespent_list.php', + 'langs' => 'dolisirh@dolisirh', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position' => 1000 + $r, + 'enabled' => '$conf->dolisirh->enabled', // Define condition to show or hide menu entry. Use '$conf->dolisirh->enabled' if entry must be visible if module is enabled. + 'perms' => '1', // Use 'perms'=>'$user->rights->dolisirh->myobject->read' if you want your menu with a permission rules + 'target' => '', + 'user' => 2, // 0=Menu for internal users, 1=external users, 2=both + ); + + $this->menu[$r++] = array( + 'fk_menu' =>'fk_mainmenu=hrm,fk_leftmenu=timespent', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'type' => 'left', // This is a Top menu entry + 'titre' => $langs->trans('AddTimeSpent'), + 'prefix' => $pictoDoliSIRH, + 'mainmenu' => 'hrm', + 'leftmenu' => 'timespent', + 'url' => '/dolisirh/view/timespent_day.php', + 'langs' => 'dolisirh@dolisirh', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position' => 48520 + $r, + 'enabled' => '$conf->dolisirh->enabled', // Define condition to show or hide menu entry. Use '$conf->dolisirh->enabled' if entry must be visible if module is enabled. + 'perms' => '$user->rights->dolisirh->lire', // Use 'perms'=>'$user->rights->dolisirh->digiriskconst->read' if you want your menu with a permission rules + 'target' => '', + 'user' => 2, // 0=Menu for internal users, 1=external users, 2=both + ); + + $this->menu[$r++] = array( + 'fk_menu' =>'fk_mainmenu=billing,fk_leftmenu=customers_bills', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'type' => 'left', // This is a Top menu entry + 'titre' => $langs->trans('RecurringInvoicesStatistics'), + 'prefix' => $pictoDoliSIRH, + 'mainmenu' => 'billing', + 'leftmenu' => 'customers_bills', + 'url' => '/dolisirh/view/recurringinvoicestatistics.php', + 'langs' => 'dolisirh@dolisirh', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position' => 1000 + $r, + 'enabled' => '$conf->dolisirh->enabled && $conf->facture->enabled', // Define condition to show or hide menu entry. Use '$conf->dolisirh->enabled' if entry must be visible if module is enabled. + 'perms' => '$user->rights->dolisirh->lire && $user->rights->facture->lire', // Use 'perms'=>'$user->rights->dolisirh->digiriskconst->read' if you want your menu with a permission rules + 'target' => '', + 'user' => 2, // 0=Menu for internal users, 1=external users, 2=both + ); + + $this->menu[$r++] = array( + 'fk_menu' => 'fk_mainmenu=billing,fk_leftmenu=customers_bills', + 'type' => 'left', + 'titre' => $langs->trans('Categories'), + 'mainmenu' => 'billing', + 'leftmenu' => 'customers_bills', + 'url' => '/categories/index.php?type=invoice', + 'langs' => 'dolisirh@dolisirh', + 'position' => 1100 + $r, + 'enabled' => '$conf->dolisirh->enabled && $conf->categorie->enabled', + 'perms' => '$user->rights->dolisirh->lire && $user->rights->facture->lire', + 'target' => '', + 'user' => 0, + ); + + $this->menu[$r++]=array( + 'fk_menu' => 'fk_mainmenu=dolisirh', + 'type' => 'top', + 'titre' => $langs->trans('DoliSIRH'), + 'prefix' => ' ', + 'mainmenu' => 'dolisirh', + 'leftmenu' => '', + 'url' => '/dolisirh/dolisirhindex.php', + 'langs' => 'dolisirh@dolisirh', + 'position' => 1100 + $r, + 'enabled' => '$conf->dolisirh->enabled', + 'perms' => '$user->rights->dolisirh->lire', + 'target' => '', + 'user' => 2, + ); + + $this->menu[$r++]=array( + 'fk_menu' => 'fk_mainmenu=dolisirh', + 'type' => 'left', + 'titre' => $langs->trans('TimeSheet'), + 'prefix' => ' ', + 'mainmenu' => 'dolisirh', + 'leftmenu' => 'timesheet', + 'url' => '/dolisirh/view/timesheet/timesheet_list.php', + 'langs' => 'dolisirh@dolisirh', + 'position' => 1100 + $r, + 'enabled' => '$conf->dolisirh->enabled', + 'perms' => '$user->rights->dolisirh->timesheet->read', + 'target' => '', + 'user' => 2, + ); + + $this->menu[$r++] = array( + 'fk_menu' => 'fk_mainmenu=dolisirh', + 'type' => 'left', + 'titre' => $langs->trans('Categories'), + 'prefix' => ' ', + 'mainmenu' => 'dolisirh', + 'leftmenu' => 'timesheettags', + 'url' => '/categories/index.php?type=timesheet', + 'langs' => 'dolisirh@dolisirh', + 'position' => 1100 + $r, + 'enabled' => '$conf->dolisirh->enabled && $conf->categorie->enabled', + 'perms' => '$user->rights->dolisirh->timesheet->read', + 'target' => '', + 'user' => 0, + ); + + $this->menu[$r++] = array( + 'fk_menu' => 'fk_mainmenu=dolisirh', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'type' => 'left', // This is a Left menu entry + 'titre' => $langs->trans('DoliSIRHConfig'), + 'prefix' => ' ', + 'mainmenu' => 'dolisirh', + 'leftmenu' => 'dolisirhconfig', + 'url' => '/dolisirh/admin/setup.php', + 'langs' => 'dolisirh@dolisirh', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position' => 48520 + $r, + 'enabled' => '$conf->dolisirh->enabled', // Define condition to show or hide menu entry. Use '$conf->dolisirh->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. + 'perms' => '$user->rights->dolisirh->adminpage->read', // Use 'perms'=>'$user->rights->dolisirh->level1->level2' if you want your menu with a permission rules + 'target' => '', + 'user' => 0, // 0=Menu for internal users, 1=external users, 2=both + ); + + $this->menu[$r++] = array( + 'fk_menu' => 'fk_mainmenu=dolisirh', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'type' => 'left', // This is a Left menu entry + 'titre' => $langs->transnoentities('MinimizeMenu'), + 'prefix' => ' ', + 'mainmenu' => 'dolisirh', + 'leftmenu' => '', + 'url' => '', + 'langs' => '', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position' => 48520 + $r, + 'enabled' => '$conf->dolisirh->enabled', // Define condition to show or hide menu entry. Use '$conf->dolisirh->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. + 'perms' => 1, // Use 'perms'=>'$user->rights->dolisirh->level1->level2' if you want your menu with a permission rules + 'target' => '', + 'user' => 0, // 0=Menu for internal users, 1=external users, 2=both + ); + /* END MODULEBUILDER TOPMENU */ + } + + /** + * Function called when module is enabled. + * The init function add constants, boxes, permissions and menus (defined in constructor) into Dolibarr database. + * It also creates data directories + * + * @param string $options Options when enabling module ('', 'noboxes') + * @return int 1 if OK, 0 if KO + */ + public function init($options = '') + { + global $conf, $langs, $db, $user; + $langs->load('dolisirh@dolisirh'); + + $sql = array(); + // Load sql sub folders + $sqlFolder = scandir(__DIR__ . '/../../sql'); + foreach ($sqlFolder as $subFolder) { + if ( ! preg_match('/\./', $subFolder)) { + $this->_load_tables('/dolisirh/sql/' . $subFolder . '/'); + } + } + + $result = $this->_load_tables('/dolisirh/sql/'); + if ($result < 0) { + return -1; // Do not activate module if error 'not allowed' returned when loading module SQL queries (the _load_table run sql with run_sql with the error allowed parameter set to 'default') + } + + if ($conf->global->DOLISIRH_TIMESPENT_BOOKMARK_SET < 1) { + include_once DOL_DOCUMENT_ROOT.'/bookmarks/class/bookmark.class.php'; + + $bookmark = new Bookmark($db); + + $bookmark->title = $langs->transnoentities('TimeSpent'); + $bookmark->url = DOL_URL_ROOT . '/custom/dolisirh/view/timespent_day.php?mainmenu=project'; + $bookmark->target = 0; + $bookmark->position = 10; + $bookmark->create(); + + dolibarr_set_const($db, 'DOLISIRH_TIMESPENT_BOOKMARK_SET', 1, 'integer', 0, '', $conf->entity); + } + + if ($conf->global->DOLISIRH_PRODUCT_SERVICE_SET == 0 ) { + require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; + + $product = new Product($db); + + $product->ref = $langs->transnoentities('MealTicket'); + $product->label = $langs->transnoentities('MealTicket'); + $product->create($user); + + $product->ref = $langs->transnoentities('JourneySubscription'); + $product->label = $langs->transnoentities('JourneySubscription'); + $product->type = $product::TYPE_SERVICE; + $product->create($user); + + $product->ref = $langs->transnoentities('13thMonthBonus'); + $product->label = $langs->transnoentities('13thMonthBonus'); + $product->type = $product::TYPE_SERVICE; + $product->create($user); + + $product->ref = $langs->transnoentities('SpecialBonus'); + $product->label = $langs->transnoentities('SpecialBonus'); + $product->type = 1; + $product->create($user); + + dolibarr_set_const($db, 'DOLISIRH_PRODUCT_SERVICE_SET', 1, 'integer', 0, '', $conf->entity); + } + + // Create extrafields during init + include_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php'; + $extra_fields = new ExtraFields($this->db); + + $param['options']['Task:projet/class/task.class.php'] = NULL; + $extra_fields->addExtraField('fk_task', 'Tâche', 'link', 100, NULL, 'facture', 1, 0, NULL, $param, 1, 1, 1); //extrafields invoice + unset($param); + $param['options']['Facture:compta/facture/class/facture.class.php'] = NULL; + $extra_fields->addExtraField('fk_facture_name', 'Facture', 'link', 100, NULL, 'projet_task', 1, 0, NULL, $param, 1, 1, 1); //extrafields task + unset($param); + $extra_fields->update('fk_task', 'Tâche', 'sellist', '', 'ticket', 0, 0, 100, 'a:1:{s:7:"options";a:1:{s:110:"projet_task:ref:rowid::entity = $ENTITY$ AND fk_projet = ($SEL$ fk_project FROM '. MAIN_DB_PREFIX .'ticket WHERE rowid = $ID$)";N;}}', 1, 1, '1'); + $extra_fields->addExtraField('fk_task', 'Tâche', 'sellist', 100, NULL, 'ticket', 0, 0, NULL, 'a:1:{s:7:"options";a:1:{s:110:"projet_task:ref:rowid::entity = $ENTITY$ AND fk_projet = ($SEL$ fk_project FROM '. MAIN_DB_PREFIX .'ticket WHERE rowid = $ID$)";N;}}', 1, 1, '1'); //extrafields ticket + + // Document templates + delDocumentModel('timesheetdocument_odt', 'timesheetdocument'); + addDocumentModel('timesheetdocument_odt', 'timesheetdocument', 'ODT templates', 'DOLISIRH_TIMESHEETDOCUMENT_ADDON_ODT_PATH'); + + return $this->_init(array(), $options); + } + + /** + * Function called when module is disabled. + * Remove from database constants, boxes and permissions from Dolibarr database. + * Data directories are not deleted + * + * @param string $options Options when enabling module ('', 'noboxes') + * @return int 1 if OK, 0 if KO + */ + public function remove($options = '') + { + $sql = array(); + return $this->_remove($sql, $options); + } +} diff --git a/core/tpl/dolisirh_projectcreation_action.tpl.php b/core/tpl/dolisirh_projectcreation_action.tpl.php new file mode 100644 index 0000000..f853943 --- /dev/null +++ b/core/tpl/dolisirh_projectcreation_action.tpl.php @@ -0,0 +1,119 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +if ($conf->global->DOLISIRH_HR_PROJECT < 1) { + require_once DOL_DOCUMENT_ROOT . '/core/lib/admin.lib.php'; + require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php'; + require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php'; + require_once DOL_DOCUMENT_ROOT . '/projet/class/task.class.php'; + require_once DOL_DOCUMENT_ROOT . '/core/modules/project/mod_project_simple.php'; + + $project = new Project($db); + $usertmp = new User($db); + + $obj = empty($conf->global->PROJECT_ADDON) ? 'mod_project_simple' : $conf->global->PROJECT_ADDON; + + if (!empty($conf->global->PROJECT_ADDON) && is_readable(DOL_DOCUMENT_ROOT . "/core/modules/project/" . $conf->global->PROJECT_ADDON . ".php")) { + require_once DOL_DOCUMENT_ROOT . "/core/modules/project/" . $conf->global->PROJECT_ADDON . '.php'; + $modProject = new $obj; + $projectRef = $modProject->getNextValue('', null); + } + + $project->ref = $projectRef; + $project->title = $langs->transnoentities('HumanResources') . ' - ' . $conf->global->MAIN_INFO_SOCIETE_NOM; + $project->description = $langs->transnoentities('HRDescription'); + $project->date_c = dol_now(); + $currentYear = dol_print_date(dol_now(), '%Y'); + $fiscalMonthStart = $conf->global->SOCIETE_FISCAL_MONTH_START; + $startdate = dol_mktime('0', '0', '0', $fiscalMonthStart ? $fiscalMonthStart : '1', '1', $currentYear); + $project->date_start = $startdate; + + $project->usage_task = 1; + + $startdateAddYear = dol_time_plus_duree($startdate, 1, 'y'); + $startdateAddYearMonth = dol_time_plus_duree($startdateAddYear, -1, 'd'); + $enddate = dol_print_date($startdateAddYearMonth, 'dayrfc'); + $project->date_end = $enddate; + $project->statut = 1; + + $result = $project->create($user); + + if ($result > 0) { + dolibarr_set_const($db, 'DOLISIRH_HR_PROJECT', $result, 'integer', 0, '', $conf->entity); + $usertmp->fetchAll('', '', 0, 0, array('customsql' => 'fk_soc IS NULL'), 'AND', true); + $liste_type_contacts = array_keys($project->listeTypeContacts()); + if (is_array($usertmp->users) && !empty($usertmp->users)) { + foreach ($usertmp->users as $usersingle) { + $test = $project->add_contact($usersingle->id, $liste_type_contacts[1], 'internal'); + } + } + + $task = new Task($db); + $defaultref = ''; + $obj = empty($conf->global->PROJECT_TASK_ADDON) ? 'mod_task_simple' : $conf->global->PROJECT_TASK_ADDON; + + if (!empty($conf->global->PROJECT_TASK_ADDON) && is_readable(DOL_DOCUMENT_ROOT . "/core/modules/project/task/" . $conf->global->PROJECT_TASK_ADDON . ".php")) { + require_once DOL_DOCUMENT_ROOT . "/core/modules/project/task/" . $conf->global->PROJECT_TASK_ADDON . '.php'; + $modTask = new $obj; + $defaultref = $modTask->getNextValue('', null); + } + + $task->fk_project = $result; + $task->ref = $defaultref; + $task->label = $langs->transnoentities('Holidays'); + $task->date_c = dol_now(); + $task->create($user); + + $task->fk_project = $result; + $task->ref = $modTask->getNextValue('', null);; + $task->label = $langs->transnoentities('PaidHolidays'); + $task->date_c = dol_now(); + $task->create($user); + + $task->fk_project = $result; + $task->ref = $modTask->getNextValue('', null);; + $task->label = $langs->transnoentities('SickLeave'); + $task->date_c = dol_now(); + $task->create($user); + + $task->fk_project = $result; + $task->ref = $modTask->getNextValue('', null);; + $task->label = $langs->transnoentities('PublicHoliday'); + $task->date_c = dol_now(); + $task->create($user); + + $task->fk_project = $result; + $task->ref = $modTask->getNextValue('', null);; + $task->label = $langs->trans('RTT'); + $task->date_c = dol_now(); + $task->create($user); + + $taskarray = $task->getTasksArray(0, 0, $result); + + if (is_array($usertmp->users) && !empty($usertmp->users)) { + foreach ($usertmp->users as $usersingle) { + if (is_array($taskarray) && !empty($taskarray)) { + foreach ($taskarray as $tasksingle) { + $tasksingle->add_contact($usersingle->id, $liste_type_contacts[3], 'internal'); + } + } + } + } + + dolibarr_set_const($db, 'DOLISIRH_RTT_TASK', 1, 'integer', 0, '', $conf->entity); + } +} diff --git a/core/tpl/signature/dolisirh_signature_action_view.tpl.php b/core/tpl/signature/dolisirh_signature_action_view.tpl.php new file mode 100644 index 0000000..b4b4b4a --- /dev/null +++ b/core/tpl/signature/dolisirh_signature_action_view.tpl.php @@ -0,0 +1,44 @@ +
+ + +
+ + + + diff --git a/core/tpl/signature/dolisirh_signature_view.tpl.php b/core/tpl/signature/dolisirh_signature_view.tpl.php new file mode 100644 index 0000000..4d1801e --- /dev/null +++ b/core/tpl/signature/dolisirh_signature_view.tpl.php @@ -0,0 +1,43 @@ +signature) && ($object->status == $object::STATUS_VALIDATED || $element->signature == $langs->transnoentities("FileGenerated")) && $element->status != $element::STATUS_ABSENT) : ?> + +signature)) : ?> + + + + + + + + diff --git a/core/tpl/signature/index.php b/core/tpl/signature/index.php new file mode 100644 index 0000000..cd6990e --- /dev/null +++ b/core/tpl/signature/index.php @@ -0,0 +1,2 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file core/triggers/interface_99_modDolisirh_DolisirhTriggers.class.php + * \ingroup dolisirh + * \brief DoliSIRH trigger. + */ + +require_once DOL_DOCUMENT_ROOT.'/core/triggers/dolibarrtriggers.class.php'; + +/** + * Class of triggers for DoliSIRH module + */ +class InterfaceDolisirhTriggers extends DolibarrTriggers +{ + /** + * @var DoliDB Database handler + */ + protected $db; + + /** + * Constructor + * + * @param DoliDB $db Database handler + */ + public function __construct(DoliDB $db) + { + $this->db = $db; + + $this->name = preg_replace('/^Interface/i', '', get_class($this)); + $this->family = "demo"; + $this->description = "Dolisirh triggers."; + // 'development', 'experimental', 'dolibarr' or version + $this->version = '1.3.0'; + $this->picto = 'dolisirh@dolisirh'; + } + + /** + * Trigger name + * + * @return string Name of trigger file + */ + public function getName(): string + { + return $this->name; + } + + /** + * Trigger description + * + * @return string Description of trigger file + */ + public function getDesc(): string + { + return $this->description; + } + + /** + * Function called when a Dolibarr business event is done. + * All functions "runTrigger" are triggered if file + * is inside directory core/triggers + * + * @param string $action Event action code + * @param CommonObject $object Object + * @param User $user Object user + * @param Translate $langs Object langs + * @param Conf $conf Object conf + * @return int 0 < if KO, 0 if no triggered ran, >0 if OK + * @throws Exception + */ + public function runTrigger($action, $object, User $user, Translate $langs, Conf $conf): int + { + if (empty($conf->dolisirh->enabled)) return 0; // If module is not enabled, we do nothing + + switch ($action) { + // Actions + case 'ACTION_CREATE': + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + if (((int)$object->fk_element) > 0 && $object->elementtype == 'ticket' && preg_match('/^TICKET_/',$object->code)) { + dol_syslog("Add time spent"); + $result= 0; + $ticket = new Ticket($this->db); + $result = $ticket->fetch($object->fk_element); + dol_syslog(var_export($ticket, true), LOG_DEBUG); + if ($result > 0 && ($ticket->id) > 0) { + if (is_array($ticket->array_options) && array_key_exists('options_fk_task',$ticket->array_options) && $ticket->array_options['options_fk_task']>0) { + require_once DOL_DOCUMENT_ROOT .'/projet/class/task.class.php'; + $task = new Task($this->db); + $result = $task->fetch($ticket->array_options['options_fk_task']); + dol_syslog(var_export($task, true), LOG_DEBUG); + if ($result > 0 && ($task->id) > 0) { + $task->timespent_note = $object->note_private; + $task->timespent_duration = GETPOST('timespent','int') * 60; // We store duration in seconds + $task->timespent_date = dol_now(); + $task->timespent_withhour = 1; + $task->timespent_fk_user = $user->id; + + $id_message = $task->id; + $name_message = $task->ref; + + $task->addTimeSpent($user); + setEventMessages($langs->trans("MessageTimeSpentCreate").' : '.''.$name_message.'', array()); + } else { + setEventMessages($task->error,$task->errors,'errors'); + return -1; + } + } + } else { + setEventMessages($ticket->error,$ticket->errors,'errors'); + return -1; + } + } + break; + + case 'BILL_CREATE': + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + require_once __DIR__ . '/../../lib/dolisirh_function.lib.php'; + $categories = GETPOST('categories', 'array:int'); + setCategoriesObject($categories, 'invoice', false, $object); + break; + + case 'BILLREC_CREATE': + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php'; + require_once __DIR__ . '/../../lib/dolisirh_function.lib.php'; + $cat = new Categorie($this->db); + $categories = $cat->containing(GETPOST('facid'),'invoice'); + if (is_array($categories) && !empty($categories)) { + foreach ($categories as $category) { + $categoryArray[] = $category->id; + } + } + if (!empty($categoryArray)) { + setCategoriesObject($categoryArray, 'invoicerec', false, $object); + } + break; + + // Timesheet + case 'TIMESHEET_CREATE' : + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; + require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; + + require_once __DIR__ . '/../../class/timesheet.class.php'; + + $signatory = new TimeSheetSignature($this->db); + $usertmp = new User($this->db); + $product = new Product($this->db); + $objectline = new TimeSheetLine($this->db); + $actioncomm = new ActionComm($this->db); + + if (!empty($object->fk_user_assign)) { + $usertmp->fetch($object->fk_user_assign); + } + + $signatory->setSignatory($object->id, 'timesheet', 'user', array($object->fk_user_assign), 'TIMESHEET_SOCIETY_ATTENDANT'); + $signatory->setSignatory($object->id, 'timesheet', 'user', array($usertmp->fk_user), 'TIMESHEET_SOCIETY_RESPONSIBLE'); + + $now = dol_now(); + + if ($conf->global->DOLISIRH_PRODUCT_SERVICE_SET) { + $product->fetch('', dol_sanitizeFileName(dol_string_nospecial(trim($langs->transnoentities("MealTicket"))))); + $objectline->date_creation = $object->db->idate($now); + $objectline->qty = 0; + $objectline->rang = 1; + $objectline->fk_timesheet = $object->id; + $objectline->fk_parent_line = 0; + $objectline->fk_product = $product->id; + $objectline->product_type = 0; + $objectline->insert($user); + + $product->fetch('', dol_sanitizeFileName(dol_string_nospecial(trim($langs->transnoentities("JourneySubscription"))))); + $objectline->date_creation = $object->db->idate($now); + $objectline->qty = 0; + $objectline->rang = 2; + $objectline->fk_timesheet = $object->id; + $objectline->fk_parent_line = 0; + $objectline->fk_product = $product->id; + $objectline->product_type = 1; + $objectline->insert($user); + + $product->fetch('', dol_sanitizeFileName(dol_string_nospecial(trim($langs->transnoentities("13thMonthBonus"))))); + $objectline->date_creation = $object->db->idate($now); + $objectline->qty = 0; + $objectline->rang = 3; + $objectline->fk_timesheet = $object->id; + $objectline->fk_parent_line = 0; + $objectline->fk_product = $product->id; + $objectline->product_type = 1; + $objectline->insert($user); + + $product->fetch('', dol_sanitizeFileName(dol_string_nospecial(trim($langs->transnoentities("SpecialBonus"))))); + $objectline->date_creation = $object->db->idate($now); + $objectline->qty = 0; + $objectline->rang = 4; + $objectline->fk_timesheet = $object->id; + $objectline->fk_parent_line = 0; + $objectline->fk_product = $product->id; + $objectline->product_type = 1; + $objectline->insert($user); + } + + $actioncomm->elementtype = 'timesheet@dolisirh'; + $actioncomm->code = 'AC_TIMESHEET_CREATE'; + $actioncomm->type_code = 'AC_OTH_AUTO'; + $actioncomm->label = $langs->trans('TimeSheetCreateTrigger'); + $actioncomm->datep = $now; + $actioncomm->fk_element = $object->id; + $actioncomm->userownerid = $user->id; + $actioncomm->percentage = -1; + + $actioncomm->create($user); + break; + + case 'TIMESHEET_MODIFY' : + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; + $now = dol_now(); + $actioncomm = new ActionComm($this->db); + + $actioncomm->elementtype = 'timesheet@dolisirh'; + $actioncomm->code = 'AC_TIMESHEET_MODIFY'; + $actioncomm->type_code = 'AC_OTH_AUTO'; + $actioncomm->label = $langs->trans('TimeSheetModifyTrigger'); + $actioncomm->datep = $now; + $actioncomm->fk_element = $object->id; + $actioncomm->userownerid = $user->id; + $actioncomm->percentage = -1; + + $actioncomm->create($user); + break; + + case 'TIMESHEET_DELETE' : + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; + $now = dol_now(); + $actioncomm = new ActionComm($this->db); + + $actioncomm->elementtype = 'timesheet@dolisirh'; + $actioncomm->code = 'AC_TIMESHEET_DELETE'; + $actioncomm->type_code = 'AC_OTH_AUTO'; + $actioncomm->label = $langs->trans('TimeSheetDeleteTrigger'); + $actioncomm->datep = $now; + $actioncomm->fk_element = $object->id; + $actioncomm->userownerid = $user->id; + $actioncomm->percentage = -1; + + $actioncomm->create($user); + break; + + case 'TIMESHEET_VALIDATE' : + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; + $now = dol_now(); + $actioncomm = new ActionComm($this->db); + + $actioncomm->elementtype = 'timesheet@dolisirh'; + $actioncomm->code = 'AC_TIMESHEET_VALIDATE'; + $actioncomm->type_code = 'AC_OTH_AUTO'; + $actioncomm->label = $langs->trans('TimeSheetValidateTrigger'); + $actioncomm->datep = $now; + $actioncomm->fk_element = $object->id; + $actioncomm->userownerid = $user->id; + $actioncomm->percentage = -1; + + $actioncomm->create($user); + break; + + case 'TIMESHEET_UNVALIDATE' : + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; + $now = dol_now(); + $actioncomm = new ActionComm($this->db); + + $actioncomm->elementtype = 'timesheet@dolisirh'; + $actioncomm->code = 'AC_TIMESHEET_UNVALIDATE'; + $actioncomm->type_code = 'AC_OTH_AUTO'; + $actioncomm->label = $langs->trans('TimeSheetUnValidateTrigger'); + $actioncomm->datep = $now; + $actioncomm->fk_element = $object->id; + $actioncomm->userownerid = $user->id; + $actioncomm->percentage = -1; + + $actioncomm->create($user); + break; + + case 'TIMESHEET_LOCKED' : + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; + $now = dol_now(); + $actioncomm = new ActionComm($this->db); + + $actioncomm->elementtype = 'timesheet@dolisirh'; + $actioncomm->code = 'AC_TIMESHEET_LOCKED'; + $actioncomm->type_code = 'AC_OTH_AUTO'; + $actioncomm->label = $langs->trans('TimeSheetLockedTrigger'); + $actioncomm->datep = $now; + $actioncomm->fk_element = $object->id; + $actioncomm->userownerid = $user->id; + $actioncomm->percentage = -1; + + $actioncomm->create($user); + break; + + case 'TIMESHEET_ARCHIVED' : + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; + $now = dol_now(); + $actioncomm = new ActionComm($this->db); + + $actioncomm->elementtype = 'timesheet@dolisirh'; + $actioncomm->code = 'AC_TIMESHEET_ARCHIVED'; + $actioncomm->type_code = 'AC_OTH_AUTO'; + $actioncomm->label = $langs->trans('TimeSheetArchivedTrigger'); + $actioncomm->datep = $now; + $actioncomm->fk_element = $object->id; + $actioncomm->userownerid = $user->id; + $actioncomm->percentage = -1; + + $actioncomm->create($user); + break; + + case 'ECMFILES_CREATE' : + if ($object->src_object_type == 'dolisirh_timesheet') { + dol_syslog("Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id); + require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; + + require_once __DIR__ . '/../../class/timesheet.class.php'; + + $now = dol_now(); + $signatory = new TimeSheetSignature($this->db); + $actioncomm = new ActionComm($this->db); + + $signatories = $signatory->fetchSignatories($object->src_object_id, 'timesheet'); + + if (!empty($signatories) && $signatories > 0) { + foreach ($signatories as $signatory) { + $signatory->signature = $langs->transnoentities("FileGenerated"); + $signatory->update($user, false); + } + } + + $actioncomm->elementtype = 'timesheet@dolisirh'; + $actioncomm->code = 'AC_TIMESHEET_GENERATE'; + $actioncomm->type_code = 'AC_OTH_AUTO'; + $actioncomm->label = $langs->trans('TimeSheetGenerateTrigger'); + $actioncomm->datep = $now; + $actioncomm->fk_element = $object->src_object_id; + $actioncomm->userownerid = $user->id; + $actioncomm->percentage = -1; + + $actioncomm->create($user); + } + break; + + case 'DOLISIRHSIGNATURE_ADDATTENDANT' : + dol_syslog("Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id); + require_once DOL_DOCUMENT_ROOT . '/comm/action/class/actioncomm.class.php'; + $now = dol_now(); + $actioncomm = new ActionComm($this->db); + + $actioncomm->elementtype = $object->object_type . '@dolisirh'; + $actioncomm->code = 'AC_DOLISIRHSIGNATURE_ADDATTENDANT'; + $actioncomm->type_code = 'AC_OTH_AUTO'; + $actioncomm->label = $langs->transnoentities('DoliSIRHAddAttendantTrigger', $object->firstname . ' ' . $object->lastname); + if ($object->element_type == 'socpeople') { + $actioncomm->socpeopleassigned = array($object->element_id => $object->element_id); + } + $actioncomm->datep = $now; + $actioncomm->fk_element = $object->fk_object; + $actioncomm->userownerid = $user->id; + $actioncomm->percentage = -1; + + $actioncomm->create($user); + break; + + case 'DOLISIRHSIGNATURE_SIGNED' : + dol_syslog("Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id); + require_once DOL_DOCUMENT_ROOT . '/comm/action/class/actioncomm.class.php'; + $now = dol_now(); + $actioncomm = new ActionComm($this->db); + + $actioncomm->elementtype = $object->object_type . '@dolisirh'; + $actioncomm->code = 'AC_DOLISIRHSIGNATURE_SIGNED'; + $actioncomm->type_code = 'AC_OTH_AUTO'; + + $actioncomm->label = $langs->transnoentities('DoliSIRHSignatureSignedTrigger') . ' : ' . $object->firstname . ' ' . $object->lastname; + + $actioncomm->datep = $now; + $actioncomm->fk_element = $object->fk_object; + if ($object->element_type == 'socpeople') { + $actioncomm->socpeopleassigned = array($object->element_id => $object->element_id); + } + $actioncomm->userownerid = $user->id; + $actioncomm->percentage = -1; + + $actioncomm->create($user); + break; + + case 'DOLISIRHSIGNATURE_PENDING_SIGNATURE' : + + dol_syslog("Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id); + require_once DOL_DOCUMENT_ROOT . '/comm/action/class/actioncomm.class.php'; + $now = dol_now(); + $actioncomm = new ActionComm($this->db); + + $actioncomm->elementtype = $object->object_type . '@dolisirh'; + $actioncomm->code = 'AC_DOLISIRHSIGNATURE_PENDING_SIGNATURE'; + $actioncomm->type_code = 'AC_OTH_AUTO'; + $actioncomm->label = $langs->transnoentities('DoliSIRHSignaturePendingSignatureTrigger') . ' : ' . $object->firstname . ' ' . $object->lastname; + $actioncomm->datep = $now; + $actioncomm->fk_element = $object->fk_object; + if ($object->element_type == 'socpeople') { + $actioncomm->socpeopleassigned = array($object->element_id => $object->element_id); + } + $actioncomm->userownerid = $user->id; + $actioncomm->percentage = -1; + + $actioncomm->create($user); + break; + + case 'DOLISIRHSIGNATURE_ABSENT' : + + dol_syslog("Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id); + require_once DOL_DOCUMENT_ROOT . '/comm/action/class/actioncomm.class.php'; + $now = dol_now(); + $actioncomm = new ActionComm($this->db); + + $actioncomm->elementtype = $object->object_type . '@dolisirh'; + $actioncomm->code = 'AC_DOLISIRHSIGNATURE_ABSENT'; + $actioncomm->type_code = 'AC_OTH_AUTO'; + $actioncomm->label = $langs->transnoentities('DoliSIRHSignatureAbsentTrigger') . ' : ' . $object->firstname . ' ' . $object->lastname; + $actioncomm->datep = $now; + $actioncomm->fk_element = $object->fk_object; + if ($object->element_type == 'socpeople') { + $actioncomm->socpeopleassigned = array($object->element_id => $object->element_id); + } + $actioncomm->userownerid = $user->id; + $actioncomm->percentage = -1; + + $actioncomm->create($user); + break; + + case 'DOLISIRHSIGNATURE_DELETED' : + + dol_syslog("Trigger '" . $this->name . "' for action '$action' launched by " . __FILE__ . ". id=" . $object->id); + require_once DOL_DOCUMENT_ROOT . '/comm/action/class/actioncomm.class.php'; + $now = dol_now(); + $actioncomm = new ActionComm($this->db); + + $actioncomm->elementtype = $object->object_type . '@dolisirh'; + $actioncomm->code = 'AC_DOLISIRHSIGNATURE_DELETED'; + $actioncomm->type_code = 'AC_OTH_AUTO'; + $actioncomm->label = $langs->transnoentities('DoliSIRHSignatureDeletedTrigger') . ' : ' . $object->firstname . ' ' . $object->lastname; + $actioncomm->datep = $now; + $actioncomm->fk_element = $object->fk_object; + if ($object->element_type == 'socpeople') { + $actioncomm->socpeopleassigned = array($object->element_id => $object->element_id); + } + $actioncomm->userownerid = $user->id; + $actioncomm->percentage = -1; + + $actioncomm->create($user); + break; + + default: + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + break; + } + return 0; + } +} diff --git a/css/dolisirh.css b/css/dolisirh.css new file mode 100644 index 0000000..5b97947 --- /dev/null +++ b/css/dolisirh.css @@ -0,0 +1,2702 @@ +@charset "UTF-8"; +.wpeo-modal .title { + display: block; + font-weight: 600; + font-size: 13px; + margin-bottom: 0.6em; + color: rgba(0, 0, 0, 0.8); +} +.wpeo-modal input[type=text], +.wpeo-modal input[type=email], +.wpeo-modal input[type=url], +.wpeo-modal input[type=password], +.wpeo-modal input[type=search], +.wpeo-modal input[type=number], +.wpeo-modal input[type=tel], +.wpeo-modal input[type=range], +.wpeo-modal input[type=date], +.wpeo-modal input[type=month], +.wpeo-modal input[type=week], +.wpeo-modal input[type=time], +.wpeo-modal input[type=datetime], +.wpeo-modal input[type=datetime-local], +.wpeo-modal input[type=color], +.wpeo-modal select, +.wpeo-modal textarea { + width: 100%; + border: 1px solid rgba(0, 0, 0, 0.2); + padding: 1em; +} +.wpeo-modal input[type=text]:focus, +.wpeo-modal input[type=email]:focus, +.wpeo-modal input[type=url]:focus, +.wpeo-modal input[type=password]:focus, +.wpeo-modal input[type=search]:focus, +.wpeo-modal input[type=number]:focus, +.wpeo-modal input[type=tel]:focus, +.wpeo-modal input[type=range]:focus, +.wpeo-modal input[type=date]:focus, +.wpeo-modal input[type=month]:focus, +.wpeo-modal input[type=week]:focus, +.wpeo-modal input[type=time]:focus, +.wpeo-modal input[type=datetime]:focus, +.wpeo-modal input[type=datetime-local]:focus, +.wpeo-modal input[type=color]:focus, +.wpeo-modal select:focus, +.wpeo-modal textarea:focus { + border: 1px solid rgba(0, 0, 0, 0.6); +} +.wpeo-modal select { + padding: 1em 0; +} + +.form-label-required::after { + display: inline-block; + content: "*"; + color: #e05353; + font-size: 22px; + line-height: 0; + position: relative; + top: 4px; + left: 4px; +} + +.pictoDoliSIRH { + vertical-align: middle; + width: 24px; + margin-right: 2px; +} + +/*-------------------------------------------------------------- + Module : Dropdown + Version : 1.0.0 + + .wpeo-dropdown -> classe de base du mobule + .grid -> Affichage en grille + .list -> Affichage en liste +--------------------------------------------------------------*/ +.wpeo-dropdown { + position: relative; + display: inline-block; +} +.wpeo-dropdown .dropdown-toggle { + display: inline-block; +} +.wpeo-dropdown .dropdown-toggle span ~ *[class*=icon] { + margin-left: 10px; +} +.wpeo-dropdown .dropdown-content { + opacity: 0; + pointer-events: none; + -webkit-transform: translateY(-10px); + transform: translateY(-10px); + -webkit-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; + position: absolute; + background: #fff; + z-index: 99; + border: 1px solid rgba(0, 0, 0, 0.1); + -webkit-box-shadow: 0 0 10px 0px rgba(0, 0, 0, 0.3); + box-shadow: 0 0 10px 0px rgba(0, 0, 0, 0.3); + width: 220px; + padding: 0.6em; +} +.wpeo-dropdown.dropdown-active .dropdown-content { + opacity: 1; + pointer-events: auto; + -webkit-transform: translateY(0); + transform: translateY(0); +} +.wpeo-dropdown ul, .wpeo-dropdown li { + margin: 0; + list-style-type: none; + padding: 0; +} +.wpeo-dropdown .dropdown-item { + display: block; + color: rgba(0, 0, 0, 0.7); + text-decoration: none; +} +.wpeo-dropdown .dropdown-item::before { + display: none; + content: ""; +} +.wpeo-dropdown .dropdown-item .dropdown-result-title, .wpeo-dropdown .dropdown-item .dropdown-result-subtitle { + display: block; +} +.wpeo-dropdown .dropdown-item .dropdown-result-title { + font-size: 14px; +} +.wpeo-dropdown .dropdown-item .dropdown-result-subtitle { + font-size: 12px; + color: rgba(0, 0, 0, 0.5); +} + +/** Taille */ +.wpeo-dropdown.dropdown-small .dropdown-content { + width: 60px; +} +.wpeo-dropdown.dropdown-medium .dropdown-content { + width: 220px; +} +.wpeo-dropdown.dropdown-large .dropdown-content { + width: 360px; +} + +/** Padding */ +.wpeo-dropdown.dropdown-padding-0 .dropdown-content { + padding: 0; +} +.wpeo-dropdown.dropdown-padding-1 .dropdown-content { + padding: 0.6em; +} +.wpeo-dropdown.dropdown-padding-2 .dropdown-content { + padding: 1.2em; +} + +/** Alignement */ +.wpeo-dropdown.dropdown-left .dropdown-content { + left: 0; +} +.wpeo-dropdown.dropdown-right .dropdown-content { + right: 0; +} +.wpeo-dropdown.dropdown-horizontal.dropdown-left .dropdown-content { + left: 100%; +} +.wpeo-dropdown.dropdown-horizontal.dropdown-right .dropdown-content { + right: 100%; +} + +/** Sens */ +.wpeo-dropdown.dropdown-horizontal .dropdown-content { + top: 0; + width: auto !important; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; +} + +/** Disable */ +.wpeo-dropdown .dropdown-item.dropdown-item-disable { + opacity: 0.6; + cursor: default !important; + pointer-events: none; +} +.wpeo-dropdown .dropdown-content .dropdown-item { + padding: 0.6em; + background: #fff; + -webkit-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; +} +.wpeo-dropdown .dropdown-content .dropdown-item:hover { + cursor: pointer; + background: rgba(0, 0, 0, 0.1); +} + +.wpeo-dropdown.dropdown-list .dropdown-content { + text-align: left; +} +.wpeo-dropdown.dropdown-list .dropdown-item::after { + display: block; + content: ""; + clear: both; +} +.wpeo-dropdown.dropdown-list .dropdown-item img { + float: left; + margin-right: 0.4em; +} + +.wpeo-dropdown.dropdown-grid .dropdown-item img { + width: 100%; + height: auto; + display: block; + margin: 0; +} + +/*-------------------------------------------------------------- + Module : Button + Version : 1.2.0 + + * Les boutons se forment grâce à leurs classes CSS + * .button -> classe de base pour un bouton + * .primary + * .light + * .dark + * .red + * .yellow + * .blue + * .green + * .transparent + * .bordered -> Change l'affichage du bouton. Fonctionne avec les même couleurs + * .strong -> texte en gras + * .uppercase -> texte en majuscule + * .float-right -> float right + * .float-left -> float left + * .square-30 -> bouton carré 30px + * .square-40 -> bouton carré 40px + * .square-50 -> bouton carré 50px + * .square-60 -> bouton carré 60px + * .margin -> margin haut et bas sur le bouton + * .radius-1 -> Arrondis les bords + * .radius-3 -> Arrondis les bords + * .radius-3 -> Arrondis les bords + * .rounded -> bouton en forme de rond + * .disable -> désactive les actions sur le bouton + * .size-small -> petite taille + * .size-large -> grande taille +--------------------------------------------------------------*/ +.wpeo-button { + display: inline-block; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + background: none; + text-decoration: none; + padding: 6px 14px; + line-height: 1.4; + vertical-align: middle; + height: auto; + border-radius: 0; + -webkit-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; + position: relative; + border-width: 3px; + border-style: solid; + font-size: 16px; + -webkit-box-sizing: border-box; + box-sizing: border-box; + background: #0d8aff; + border-color: #0d8aff; + color: #fff; +} +.wpeo-button:focus, .wpeo-button:visited { + color: #fff; +} +.wpeo-button:hover { + color: #fff; + -webkit-box-shadow: inset 0 -2.6em rgba(255, 255, 255, 0.25); + box-shadow: inset 0 -2.6em rgba(255, 255, 255, 0.25); + cursor: pointer; + text-decoration: none; +} +.wpeo-button:focus, .wpeo-button:active { + outline: none; +} + +/** Colors */ +.wpeo-button { + /* par défaut */ + background: #0d8aff; + border-color: #0d8aff; + color: #fff; +} +.wpeo-button.button-main { + background: #0d8aff; + border-color: #0d8aff; + color: #fff; +} +.wpeo-button.button-secondary { + background: #263C5C; + border-color: #263C5C; + color: #fff; +} +.wpeo-button.button-light { + background: #fff; + border-color: #fff; + color: #333333; +} +.wpeo-button.button-light:hover { + -webkit-box-shadow: inset 0 -2.6em rgba(0, 0, 0, 0.1); + box-shadow: inset 0 -2.6em rgba(0, 0, 0, 0.1); + color: #333333; +} +.wpeo-button.button-dark { + background: #2b2b2b; + border-color: #2b2b2b; +} +.wpeo-button.button-grey { + background: #ececec; + border-color: #ececec; + color: #333333; +} +.wpeo-button.button-grey:hover { + -webkit-box-shadow: inset 0 -2.6em rgba(0, 0, 0, 0.1); + box-shadow: inset 0 -2.6em rgba(0, 0, 0, 0.1); + color: #333333; +} +.wpeo-button.button-red { + background: #e05353; + border-color: #e05353; +} +.wpeo-button.button-yellow { + background: #e9ad4f; + border-color: #e9ad4f; +} +.wpeo-button.button-blue { + background: #0d8aff; + border-color: #0d8aff; +} +.wpeo-button.button-green { + background: #47e58e; + border-color: #47e58e; +} +.wpeo-button.button-transparent { + background: transparent; + border-color: transparent; + color: rgba(51, 51, 51, 0.4); +} +.wpeo-button.button-transparent:hover { + color: #333333; + -webkit-box-shadow: inset 0 -2.6em rgba(255, 255, 255, 0); + box-shadow: inset 0 -2.6em rgba(255, 255, 255, 0); +} + +.wpeo-button.button-bordered { + background: none; + /* Par defaut */ + border-color: #0d8aff; + color: #0d8aff; +} +.wpeo-button.button-bordered.button-main { + border-color: #0d8aff; + color: #0d8aff; +} +.wpeo-button.button-bordered.button-main:hover { + -webkit-box-shadow: inset 0 -2.6em #0d8aff; + box-shadow: inset 0 -2.6em #0d8aff; + color: #fff; +} +.wpeo-button.button-bordered.button-light { + border-color: #fff; + color: #fff; +} +.wpeo-button.button-bordered.button-light:hover { + -webkit-box-shadow: inset 0 -2.6em #fff; + box-shadow: inset 0 -2.6em #fff; + color: #333333; +} +.wpeo-button.button-bordered.button-dark { + border-color: #2b2b2b; + color: #2b2b2b; +} +.wpeo-button.button-bordered.button-dark:hover { + -webkit-box-shadow: inset 0 -2.6em #2b2b2b; + box-shadow: inset 0 -2.6em #2b2b2b; +} +.wpeo-button.button-bordered.button-grey { + border-color: #ececec; + color: #a0a0a0; +} +.wpeo-button.button-bordered.button-grey:hover { + -webkit-box-shadow: inset 0 -2.6em #ececec; + box-shadow: inset 0 -2.6em #ececec; + color: #333333; +} +.wpeo-button.button-bordered.button-red { + border-color: #e05353; + color: #e05353; +} +.wpeo-button.button-bordered.button-red:hover { + -webkit-box-shadow: inset 0 -2.6em #e05353; + box-shadow: inset 0 -2.6em #e05353; +} +.wpeo-button.button-bordered.button-yellow { + border-color: #e9ad4f; + color: #e9ad4f; +} +.wpeo-button.button-bordered.button-yellow:hover { + -webkit-box-shadow: inset 0 -2.6em #e9ad4f; + box-shadow: inset 0 -2.6em #e9ad4f; +} +.wpeo-button.button-bordered.button-blue { + border-color: #0d8aff; + color: #0d8aff; +} +.wpeo-button.button-bordered.button-blue:hover { + -webkit-box-shadow: inset 0 -2.6em #0d8aff; + box-shadow: inset 0 -2.6em #0d8aff; +} +.wpeo-button.button-bordered.button-green { + border-color: #47e58e; + color: #47e58e; +} +.wpeo-button.button-bordered.button-green:hover { + -webkit-box-shadow: inset 0 -2.6em #47e58e; + box-shadow: inset 0 -2.6em #47e58e; +} +.wpeo-button.button-bordered:hover { + -webkit-box-shadow: inset 0 -2.6em #0d8aff; + box-shadow: inset 0 -2.6em #0d8aff; + color: #fff; +} + +.wpeo-button .button-add { + position: absolute; + top: 0.4em; + right: 0.2em; + opacity: 0.6; + font-size: 14px; + -webkit-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; +} +.wpeo-button:hover .button-add { + opacity: 0.8; +} + +.wpeo-button.button-square-40 .button-add { + top: 0.1em; + right: 0; +} + +.wpeo-button .button-icon, .wpeo-button span { + position: relative; +} +.wpeo-button .button-icon ~ span { + margin-left: 10px; +} +.wpeo-button span ~ .button-icon { + margin-left: 10px; +} + +.wpeo-button.button-strong span { + font-weight: 800; +} + +.wpeo-button.button-uppercase span { + text-transform: uppercase; + font-size: 14px; +} + +.wpeo-button[class*=button-square-] { + text-align: center; + overflow: hidden; + padding: 0; +} + +.wpeo-button.button-square-30 { + width: 30px; + height: 30px; + line-height: 24px; +} +.wpeo-button.button-square-30 .button-icon { + font-size: 12px; + line-height: 24px; +} + +.wpeo-button.button-square-40 { + width: 40px; + height: 40px; + line-height: 34px; +} +.wpeo-button.button-square-40 .button-icon { + line-height: 34px; +} + +.wpeo-button.button-square-50 { + width: 50px; + height: 50px; + line-height: 44px; +} +.wpeo-button.button-square-50 .button-icon { + line-height: 44px; +} + +.wpeo-button.button-square-60 { + width: 60px; + height: 60px; + line-height: 54px; +} +.wpeo-button.button-square-60 .button-icon { + line-height: 54px; +} + +.wpeo-button.button-float-left { + float: left; +} +.wpeo-button.button-float-right { + float: right; +} + +.wpeo-button.button-margin { + margin: 1em 0; +} + +.wpeo-button.button-radius-1 { + border-radius: 2px; +} +.wpeo-button.button-radius-2 { + border-radius: 4px; +} +.wpeo-button.button-radius-3 { + border-radius: 6px; +} +.wpeo-button.button-rounded { + border-radius: 50%; +} + +.wpeo-button.button-disable { + background: #ececec !important; + border-color: #ececec !important; + color: rgba(0, 0, 0, 0.4) !important; + pointer-events: none; +} +.wpeo-button.button-disable:hover { + -webkit-box-shadow: none !important; + box-shadow: none !important; +} +.wpeo-button.button-disable.button-event { + pointer-events: all; +} + +.wpeo-button.button-size-small { + font-size: 14px; +} +.wpeo-button.button-size-small.button-uppercase span { + font-size: 12px; +} + +.wpeo-button.button-size-large { + font-size: 18px; +} +.wpeo-button.button-size-large.button-uppercase span { + font-size: 16px; +} + +/*-------------------------------------------------------------- + Module : Modal + Version : 1.0.0 + + .wpeo-modal -> classe de base du mobule + .modalactive -> lance l'apparition de la modal + .no-modal-close -> désactive l'icone fermeture +--------------------------------------------------------------*/ +.wpeo-modal { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1000; + background: rgba(39, 42, 53, 0.9); + opacity: 0; + pointer-events: none; + -webkit-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; +} +.wpeo-modal textarea { + resize: none; +} +.wpeo-modal.modal-active { + opacity: 1; + pointer-events: auto; + z-index: 1002; +} +.wpeo-modal.modal-active .modal-container { + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); +} +.wpeo-modal.modal-active textarea { + resize: both; +} +.wpeo-modal.modal-active .modal-active { + z-index: 1003; +} +.wpeo-modal.modal-active .modal-active .modal-active { + z-index: 1004; +} +.wpeo-modal.modal-force-display .modal-close { + display: none; +} + +.wpeo-modal .modal-container { + position: absolute; + -webkit-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; + width: 100%; + max-width: 860px; + height: 100%; + max-height: 560px; + background: #fff; + padding: 1em 0; + margin: auto; + top: 50%; + left: 50%; + -webkit-transform: translate(-50%, -60%); + transform: translate(-50%, -60%); +} +@media (max-width: 480px) { + .wpeo-modal .modal-container { + padding: 1em; + } +} +.wpeo-modal .modal-container .modal-header { + height: 10%; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + padding: 0 2em; +} +.wpeo-modal .modal-container .modal-content { + height: 78%; + padding: 0 2em; +} +.wpeo-modal .modal-container .modal-footer { + height: 12%; + padding: 0 2em; +} +.wpeo-modal .modal-container .modal-header .modal-title, .wpeo-modal .modal-container .modal-header .modal-close { + margin: auto 0; +} +.wpeo-modal .modal-container .modal-header .modal-title { + text-transform: uppercase; + font-size: 18px; + white-space: normal; +} +@media (max-width: 770px) { + .wpeo-modal .modal-container .modal-header .modal-title { + font-size: 16px; + } +} +@media (max-width: 480px) { + .wpeo-modal .modal-container .modal-header .modal-title { + font-size: 14px; + } +} +.wpeo-modal .modal-container .modal-header .modal-close { + margin-left: auto; + color: rgba(0, 0, 0, 0.3); + padding: 4px; + -webkit-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; +} +.wpeo-modal .modal-container .modal-header .modal-close:hover { + cursor: pointer; + color: #0d8aff; +} +.wpeo-modal .modal-container .modal-content { + overflow-y: auto; + font-size: 14px; +} +@media (max-width: 480px) { + .wpeo-modal .modal-container .modal-content { + font-size: 12px; + } +} +.wpeo-modal .modal-container .modal-footer { + text-align: right; + padding-top: 1em; +} +.wpeo-modal .modal-container .modal-footer.left { + text-align: left; +} +.wpeo-modal .modal-container .modal-footer.center { + text-align: center; +} + +/*-------------------------------------------------------------- + Module : Loader + Version : 1.0.0 + + .wpeo-loader => classe de base pour le module + .loader-spin => icone de chargement +--------------------------------------------------------------*/ +.wpeo-loader { + -webkit-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; + pointer-events: none; + opacity: 0.5; + position: relative; +} +.wpeo-loader .loader-spin { + position: absolute; + border: 3px solid #a7a7a7; + border-top: 3px solid #002140; + border-radius: 50%; + width: 20px; + height: 20px; + z-index: 99; + left: 50%; + top: 50%; + margin: 0 !important; + padding: 0 !important; + -webkit-animation: loader-spin 1s ease-out infinite; + animation: loader-spin 1s ease-out infinite; +} + +@-webkit-keyframes loader-spin { + 0% { + -webkit-transform: translate(-50%, -50%) rotate(0deg); + transform: translate(-50%, -50%) rotate(0deg); + } + 100% { + -webkit-transform: translate(-50%, -50%) rotate(360deg); + transform: translate(-50%, -50%) rotate(360deg); + } +} + +@keyframes loader-spin { + 0% { + -webkit-transform: translate(-50%, -50%) rotate(0deg); + transform: translate(-50%, -50%) rotate(0deg); + } + 100% { + -webkit-transform: translate(-50%, -50%) rotate(360deg); + transform: translate(-50%, -50%) rotate(360deg); + } +} +/*-------------------------------------------------------------- + Module : Gridlayout + Version : 1.5.0 + + * Classes pour l'élément parent + .wpeo-gridlayout -> classe de base du mobule + .grid-X -> Définit le nombre de colonnes + .grid-margin-X -> Ajoute des marges au dessus et en dessous du parent + .grid-gap-X -> Définit les gouttières des colonnes + + * Classes pour les enfants direct + .gridw-X -> Change la largeur du bloc enfant (gridw-2 = 2 fois la taille initiale) + .gridh-X -> Change la hauteur du bloc enfant (gridh-2 = 2 fois la taille initiale) +--------------------------------------------------------------*/ +.wpeo-gridlayout { + display: grid; + grid-gap: 1em 1em; + grid-template-columns: repeat(4, 1fr); +} + +/** Définition des tailles */ +.wpeo-gridlayout { + /** Du parent */ + /** Chaque enfant peut modifier sa propre taille */ + /** Chaque enfant peut modifier sa propre taille */ + /** Chaque enfant peut modifier sa propre taille */ + /** Chaque enfant peut modifier sa propre taille */ + /** Chaque enfant peut modifier sa propre taille */ + /** Chaque enfant peut modifier sa propre taille */ +} +.wpeo-gridlayout.grid-1 { + grid-template-columns: repeat(1, 1fr); +} +.wpeo-gridlayout.grid-1 > .gridw-1 { + grid-column: auto/span 1; +} +.wpeo-gridlayout.grid-2 { + grid-template-columns: repeat(2, 1fr); +} +.wpeo-gridlayout.grid-2 > .gridw-1 { + grid-column: auto/span 1; +} +.wpeo-gridlayout.grid-2 > .gridw-2 { + grid-column: auto/span 2; +} +@media (max-width: 770px) { + .wpeo-gridlayout.grid-2 > .gridw-2 { + grid-column: auto/span 2; + } +} +.wpeo-gridlayout.grid-3 { + grid-template-columns: repeat(3, 1fr); +} +.wpeo-gridlayout.grid-3 > .gridw-1 { + grid-column: auto/span 1; +} +.wpeo-gridlayout.grid-3 > .gridw-2 { + grid-column: auto/span 2; +} +@media (max-width: 770px) { + .wpeo-gridlayout.grid-3 > .gridw-2 { + grid-column: auto/span 2; + } +} +.wpeo-gridlayout.grid-3 > .gridw-3 { + grid-column: auto/span 3; +} +@media (max-width: 770px) { + .wpeo-gridlayout.grid-3 > .gridw-3 { + grid-column: auto/span 2; + } +} +.wpeo-gridlayout.grid-4 { + grid-template-columns: repeat(4, 1fr); +} +.wpeo-gridlayout.grid-4 > .gridw-1 { + grid-column: auto/span 1; +} +.wpeo-gridlayout.grid-4 > .gridw-2 { + grid-column: auto/span 2; +} +@media (max-width: 770px) { + .wpeo-gridlayout.grid-4 > .gridw-2 { + grid-column: auto/span 2; + } +} +.wpeo-gridlayout.grid-4 > .gridw-3 { + grid-column: auto/span 3; +} +@media (max-width: 770px) { + .wpeo-gridlayout.grid-4 > .gridw-3 { + grid-column: auto/span 2; + } +} +.wpeo-gridlayout.grid-4 > .gridw-4 { + grid-column: auto/span 4; +} +@media (max-width: 770px) { + .wpeo-gridlayout.grid-4 > .gridw-4 { + grid-column: auto/span 2; + } +} +.wpeo-gridlayout.grid-5 { + grid-template-columns: repeat(5, 1fr); +} +.wpeo-gridlayout.grid-5 > .gridw-1 { + grid-column: auto/span 1; +} +.wpeo-gridlayout.grid-5 > .gridw-2 { + grid-column: auto/span 2; +} +@media (max-width: 770px) { + .wpeo-gridlayout.grid-5 > .gridw-2 { + grid-column: auto/span 2; + } +} +.wpeo-gridlayout.grid-5 > .gridw-3 { + grid-column: auto/span 3; +} +@media (max-width: 770px) { + .wpeo-gridlayout.grid-5 > .gridw-3 { + grid-column: auto/span 2; + } +} +.wpeo-gridlayout.grid-5 > .gridw-4 { + grid-column: auto/span 4; +} +@media (max-width: 770px) { + .wpeo-gridlayout.grid-5 > .gridw-4 { + grid-column: auto/span 2; + } +} +.wpeo-gridlayout.grid-5 > .gridw-5 { + grid-column: auto/span 5; +} +@media (max-width: 770px) { + .wpeo-gridlayout.grid-5 > .gridw-5 { + grid-column: auto/span 2; + } +} +.wpeo-gridlayout.grid-6 { + grid-template-columns: repeat(6, 1fr); +} +.wpeo-gridlayout.grid-6 > .gridw-1 { + grid-column: auto/span 1; +} +.wpeo-gridlayout.grid-6 > .gridw-2 { + grid-column: auto/span 2; +} +@media (max-width: 770px) { + .wpeo-gridlayout.grid-6 > .gridw-2 { + grid-column: auto/span 2; + } +} +.wpeo-gridlayout.grid-6 > .gridw-3 { + grid-column: auto/span 3; +} +@media (max-width: 770px) { + .wpeo-gridlayout.grid-6 > .gridw-3 { + grid-column: auto/span 2; + } +} +.wpeo-gridlayout.grid-6 > .gridw-4 { + grid-column: auto/span 4; +} +@media (max-width: 770px) { + .wpeo-gridlayout.grid-6 > .gridw-4 { + grid-column: auto/span 2; + } +} +.wpeo-gridlayout.grid-6 > .gridw-5 { + grid-column: auto/span 5; +} +@media (max-width: 770px) { + .wpeo-gridlayout.grid-6 > .gridw-5 { + grid-column: auto/span 2; + } +} +.wpeo-gridlayout.grid-6 > .gridw-6 { + grid-column: auto/span 6; +} +@media (max-width: 770px) { + .wpeo-gridlayout.grid-6 > .gridw-6 { + grid-column: auto/span 2; + } +} + +/** Définition des hauteur des enfants */ +.wpeo-gridlayout > .gridh-1 { + grid-row: auto/span 1; +} +@media (max-width: 770px) { + .wpeo-gridlayout > .gridh-1 { + grid-row: auto/span 1 !important; + } +} +.wpeo-gridlayout > .gridh-2 { + grid-row: auto/span 2; +} +@media (max-width: 770px) { + .wpeo-gridlayout > .gridh-2 { + grid-row: auto/span 1 !important; + } +} +.wpeo-gridlayout > .gridh-3 { + grid-row: auto/span 3; +} +@media (max-width: 770px) { + .wpeo-gridlayout > .gridh-3 { + grid-row: auto/span 1 !important; + } +} +.wpeo-gridlayout > .gridh-4 { + grid-row: auto/span 4; +} +@media (max-width: 770px) { + .wpeo-gridlayout > .gridh-4 { + grid-row: auto/span 1 !important; + } +} +.wpeo-gridlayout > .gridh-5 { + grid-row: auto/span 5; +} +@media (max-width: 770px) { + .wpeo-gridlayout > .gridh-5 { + grid-row: auto/span 1 !important; + } +} +.wpeo-gridlayout > .gridh-6 { + grid-row: auto/span 6; +} +@media (max-width: 770px) { + .wpeo-gridlayout > .gridh-6 { + grid-row: auto/span 1 !important; + } +} + +/** Marges */ +.wpeo-gridlayout.grid-margin-0 { + margin: 0em 0; +} +.wpeo-gridlayout.grid-margin-1 { + margin: 1em 0; +} +.wpeo-gridlayout.grid-margin-2 { + margin: 2em 0; +} +.wpeo-gridlayout.grid-margin-3 { + margin: 3em 0; +} +.wpeo-gridlayout.grid-margin-4 { + margin: 4em 0; +} +.wpeo-gridlayout.grid-margin-5 { + margin: 5em 0; +} +.wpeo-gridlayout.grid-margin-6 { + margin: 6em 0; +} + +/** Gouttières */ +.wpeo-gridlayout.grid-gap-0 { + grid-gap: 0em 0em; +} +.wpeo-gridlayout.grid-gap-1 { + grid-gap: 1em 1em; +} +.wpeo-gridlayout.grid-gap-2 { + grid-gap: 2em 2em; +} +.wpeo-gridlayout.grid-gap-3 { + grid-gap: 3em 3em; +} +.wpeo-gridlayout.grid-gap-4 { + grid-gap: 4em 4em; +} +.wpeo-gridlayout.grid-gap-5 { + grid-gap: 5em 5em; +} +.wpeo-gridlayout.grid-gap-6 { + grid-gap: 6em 6em; +} + +/** Alignements */ +.wpeo-gridlayout .grid-align-center { + margin-left: auto; + margin-right: auto; +} +.wpeo-gridlayout .grid-align-right { + margin-left: auto; +} +.wpeo-gridlayout .grid-align-middle { + margin-top: auto; + margin-bottom: auto; +} +.wpeo-gridlayout .grid-align-bottom { + margin-top: auto; +} + +/** Media queries */ +@media (max-width: 480px) { + .wpeo-gridlayout:not(.dropdown-content).grid-2 { + grid-template-columns: repeat(1, 1fr) !important; + } +} +@media (max-width: 770px) { + .wpeo-gridlayout:not(.dropdown-content).grid-3 { + grid-template-columns: repeat(2, 1fr) !important; + } +} +@media (max-width: 480px) { + .wpeo-gridlayout:not(.dropdown-content).grid-3 { + grid-template-columns: repeat(1, 1fr) !important; + } +} +@media (max-width: 770px) { + .wpeo-gridlayout:not(.dropdown-content).grid-4 { + grid-template-columns: repeat(2, 1fr) !important; + } +} +@media (max-width: 480px) { + .wpeo-gridlayout:not(.dropdown-content).grid-4 { + grid-template-columns: repeat(1, 1fr) !important; + } +} +@media (max-width: 770px) { + .wpeo-gridlayout:not(.dropdown-content).grid-5 { + grid-template-columns: repeat(2, 1fr) !important; + } +} +@media (max-width: 480px) { + .wpeo-gridlayout:not(.dropdown-content).grid-5 { + grid-template-columns: repeat(1, 1fr) !important; + } +} +@media (max-width: 770px) { + .wpeo-gridlayout:not(.dropdown-content).grid-6 { + grid-template-columns: repeat(2, 1fr) !important; + } +} +@media (max-width: 480px) { + .wpeo-gridlayout:not(.dropdown-content).grid-6 { + grid-template-columns: repeat(1, 1fr) !important; + } +} +@media (max-width: 480px) { + .wpeo-gridlayout:not(.dropdown-content) > * { + grid-column: auto/span 1 !important; + } +} + +/*-------------------------------------------------------------- + Module : Table + Version : 1.0.0 + .wpeo-table -> classe de base du mobule +--------------------------------------------------------------*/ +/*-------------------------------------------------------------- + Table Flex + + .table-25 : max-width: 25px + .table-50 : max-width: 50px + .table-75 : max-width: 75px + .table-100 : max-width: 100px + ... + .table-500 : max-width: 500px; + + .table-end : Utiliser la classe table-end justifie la cellule sur la droite + .table-padding-0 : Enleve les marges internes d’une cellule +--------------------------------------------------------------*/ +.wpeo-table.table-flex { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + font-size: 14px; +} + +/** Ligne */ +.wpeo-table.table-flex .table-row { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; +} +.wpeo-table.table-flex .table-row:not(.table-header):nth-of-type(odd) { + background: rgba(0, 0, 0, 0.05); +} + +/** Ligne entete */ +.wpeo-table.table-flex .table-row.table-header { + background: #263C5C; +} +.wpeo-table.table-flex .table-row.table-header .table-cell { + font-weight: 700; + color: #fff; +} + +/** Cellule */ +.wpeo-table.table-flex .table-cell { + margin: auto 0; + width: 100%; + padding: 0.8em 0.6em; +} +@media (max-width: 770px) { + .wpeo-table.table-flex .table-cell { + padding: 0.4em; + } +} + +/** Taille générale des cellules */ +.wpeo-table.table-flex.table-1 .table-cell { + width: 100%; +} +.wpeo-table.table-flex.table-2 .table-cell { + width: 50%; +} +.wpeo-table.table-flex.table-3 .table-cell { + width: 33.3333333333%; +} +.wpeo-table.table-flex.table-4 .table-cell { + width: 25%; +} +.wpeo-table.table-flex.table-5 .table-cell { + width: 20%; +} +.wpeo-table.table-flex.table-6 .table-cell { + width: 16.6666666667%; +} +.wpeo-table.table-flex.table-7 .table-cell { + width: 14.2857142857%; +} +.wpeo-table.table-flex.table-8 .table-cell { + width: 12.5%; +} +.wpeo-table.table-flex.table-9 .table-cell { + width: 11.1111111111%; +} +.wpeo-table.table-flex.table-10 .table-cell { + width: 10%; +} + +/** Taille spécifiques des cellules */ +.wpeo-table.table-flex .table-cell.table-25 { + max-width: 25px; + min-width: 25px; +} +.wpeo-table.table-flex .table-cell.table-50 { + max-width: 50px; + min-width: 50px; +} +.wpeo-table.table-flex .table-cell.table-75 { + max-width: 75px; + min-width: 75px; +} +.wpeo-table.table-flex .table-cell.table-100 { + max-width: 100px; + min-width: 100px; +} +.wpeo-table.table-flex .table-cell.table-125 { + max-width: 125px; + min-width: 125px; +} +.wpeo-table.table-flex .table-cell.table-150 { + max-width: 150px; + min-width: 150px; +} +.wpeo-table.table-flex .table-cell.table-175 { + max-width: 175px; + min-width: 175px; +} +.wpeo-table.table-flex .table-cell.table-200 { + max-width: 200px; + min-width: 200px; +} +.wpeo-table.table-flex .table-cell.table-225 { + max-width: 225px; + min-width: 225px; +} +.wpeo-table.table-flex .table-cell.table-250 { + max-width: 250px; + min-width: 250px; +} +.wpeo-table.table-flex .table-cell.table-275 { + max-width: 275px; + min-width: 275px; +} +.wpeo-table.table-flex .table-cell.table-300 { + max-width: 300px; + min-width: 300px; +} +.wpeo-table.table-flex .table-cell.table-325 { + max-width: 325px; + min-width: 325px; +} +.wpeo-table.table-flex .table-cell.table-350 { + max-width: 350px; + min-width: 350px; +} +.wpeo-table.table-flex .table-cell.table-375 { + max-width: 375px; + min-width: 375px; +} +.wpeo-table.table-flex .table-cell.table-400 { + max-width: 400px; + min-width: 400px; +} +.wpeo-table.table-flex .table-cell.table-425 { + max-width: 425px; + min-width: 425px; +} +.wpeo-table.table-flex .table-cell.table-450 { + max-width: 450px; + min-width: 450px; +} +.wpeo-table.table-flex .table-cell.table-475 { + max-width: 475px; + min-width: 475px; +} +.wpeo-table.table-flex .table-cell.table-500 { + max-width: 500px; + min-width: 500px; +} +.wpeo-table.table-flex .table-cell.table-full { + width: 100%; +} + +/** Différentes classes */ +.wpeo-table.table-flex .table-cell.table-end { + text-align: right; + margin-left: auto; +} +.wpeo-table.table-flex .table-cell.table-padding-0 { + padding: 0; +} + +/** Responsive mobile */ +@media (max-width: 480px) { + .wpeo-table.table-flex .table-row { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + } + .wpeo-table.table-flex .table-cell { + width: 100%; + } +} +/*-------------------------------------------------------------- + Module : Tooltip + Version : 1.0.0 + + .wpeo-tooltip -> classe de base du mobule + .tooltip-primary -> tooltip sur fond rouge + .tooltip-light -> tooltip sur fond rouge + .tooltip-red -> tooltip sur fond rouge +--------------------------------------------------------------*/ +.wpeo-tooltip { + display: block; + position: absolute; + bottom: 0; + left: 0; + opacity: 0; + pointer-events: none; + z-index: 99999; + white-space: nowrap; + background: #2b2b2b; + color: #fff; + border-radius: 6px; + font-size: 0.8rem; + padding: 0 1em; + height: 2.2em; + line-height: 2.2em; +} +.wpeo-tooltip::before { + display: block; + content: ""; + width: 0; + height: 0; + border-style: solid; + position: absolute; +} +.wpeo-tooltip:focus { + outline: none; +} + +/* Couleurs */ +.wpeo-tooltip.tooltip-dark { + background: #2b2b2b; +} +.wpeo-tooltip.tooltip-dark.tooltip-top::before { + border-color: #2b2b2b transparent transparent transparent; +} +.wpeo-tooltip.tooltip-dark.tooltip-right::before { + border-color: transparent #2b2b2b transparent transparent; +} +.wpeo-tooltip.tooltip-dark.tooltip-bottom::before { + border-color: transparent transparent #2b2b2b transparent; +} +.wpeo-tooltip.tooltip-dark.tooltip-left::before { + border-color: transparent transparent transparent #2b2b2b; +} +.wpeo-tooltip.tooltip-primary { + background: #0d8aff; +} +.wpeo-tooltip.tooltip-primary.tooltip-top::before { + border-color: #0d8aff transparent transparent transparent; +} +.wpeo-tooltip.tooltip-primary.tooltip-right::before { + border-color: transparent #0d8aff transparent transparent; +} +.wpeo-tooltip.tooltip-primary.tooltip-bottom::before { + border-color: transparent transparent #0d8aff transparent; +} +.wpeo-tooltip.tooltip-primary.tooltip-left::before { + border-color: transparent transparent transparent #0d8aff; +} +.wpeo-tooltip.tooltip-light { + background: #ececec; + color: rgba(0, 0, 0, 0.6); +} +.wpeo-tooltip.tooltip-light.tooltip-top::before { + border-color: #ececec transparent transparent transparent; +} +.wpeo-tooltip.tooltip-light.tooltip-right::before { + border-color: transparent #ececec transparent transparent; +} +.wpeo-tooltip.tooltip-light.tooltip-bottom::before { + border-color: transparent transparent #ececec transparent; +} +.wpeo-tooltip.tooltip-light.tooltip-left::before { + border-color: transparent transparent transparent #ececec; +} +.wpeo-tooltip.tooltip-red { + background: #e05353; +} +.wpeo-tooltip.tooltip-red.tooltip-top::before { + border-color: #e05353 transparent transparent transparent; +} +.wpeo-tooltip.tooltip-red.tooltip-right::before { + border-color: transparent #e05353 transparent transparent; +} +.wpeo-tooltip.tooltip-red.tooltip-bottom::before { + border-color: transparent transparent #e05353 transparent; +} +.wpeo-tooltip.tooltip-red.tooltip-left::before { + border-color: transparent transparent transparent #e05353; +} + +/* Position de la fleche */ +.wpeo-tooltip.tooltip-top::before { + border-width: 6px 6px 0 6px; + border-color: #2b2b2b transparent transparent transparent; + bottom: -6px; + left: 50%; + -webkit-transform: translateX(-50%); + transform: translateX(-50%); +} +.wpeo-tooltip.tooltip-right::before { + border-width: 6px 6px 6px 0; + border-color: transparent #2b2b2b transparent transparent; + top: 50%; + -webkit-transform: translateY(-50%); + transform: translateY(-50%); + left: -6px; +} +.wpeo-tooltip.tooltip-bottom::before { + border-width: 0 6px 6px 6px; + border-color: transparent transparent #2b2b2b transparent; + top: -6px; + left: 50%; + -webkit-transform: translateX(-50%); + transform: translateX(-50%); +} +.wpeo-tooltip.tooltip-left::before { + border-width: 6px 0 6px 6px; + border-color: transparent transparent transparent #2b2b2b; + top: 50%; + -webkit-transform: translateY(-50%); + transform: translateY(-50%); + right: -6px; +} + +/*-------------------------------------------------------------- + Module : Notice + Version : 1.0.0 + + .wpeo-notice -> classe de base du mobule +--------------------------------------------------------------*/ +/* General */ +.wpeo-notice { + position: relative; + font-size: 1em; + padding: 1em; + overflow: hidden; + border-radius: 3px; + border: solid #eee 1px; + margin: 1em 0; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} +.wpeo-notice::before { + display: block; + font-family: "Font Awesome 5 Free"; + font-weight: 900; + font-size: 24px; +} +.wpeo-notice .notice-content { + width: 100%; + padding: 0 1em; + color: rgba(0, 0, 0, 0.6); +} +.wpeo-notice .notice-title { + font-size: 20px; + font-weight: 600; + color: rgba(0, 0, 0, 0.9); +} +.wpeo-notice .notice-subtitle { + font-size: 14px; +} +.wpeo-notice .notice-close { + color: rgba(0, 0, 0, 0.3); + -webkit-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; +} +.wpeo-notice .notice-close:hover { + color: #0d8aff; + cursor: pointer; +} +.wpeo-notice ul { + padding: 0 0 0 1.4em; + margin: 0.4em 0; +} + +/** Status */ +/** Info */ +.wpeo-notice.notice-info { + border-left: solid #0d8aff 6px; + color: #0d8aff; + background: rgba(13, 138, 255, 0.05); +} +.wpeo-notice.notice-info::before { + content: "\f05a"; +} +.wpeo-notice.notice-info .notice-title, .wpeo-notice.notice-info .notice-subtitle, .wpeo-notice.notice-info a { + color: #0d8aff; +} + +/** Error */ +.wpeo-notice.notice-error { + border-left: solid #e05353 6px; + color: #e05353; + background: rgba(224, 83, 83, 0.05); +} +.wpeo-notice.notice-error::before { + content: "\f057"; +} +.wpeo-notice.notice-error .notice-title, .wpeo-notice.notice-error .notice-subtitle, .wpeo-notice.notice-error a { + color: #e05353; +} + +/** Warning */ +.wpeo-notice.notice-warning { + border-left: solid #e9ad4f 6px; + color: #e9ad4f; + background: rgba(233, 173, 79, 0.05); +} +.wpeo-notice.notice-warning::before { + content: "\f071"; +} +.wpeo-notice.notice-warning .notice-title, .wpeo-notice.notice-warning .notice-subtitle, .wpeo-notice.notice-warning a { + color: #e9ad4f; +} + +/** Success */ +.wpeo-notice.notice-success { + border-left: solid #47e58e 6px; + color: #47e58e; + background: rgba(71, 229, 142, 0.05); +} +.wpeo-notice.notice-success::before { + content: "\f058"; +} +.wpeo-notice.notice-success .notice-title, .wpeo-notice.notice-success .notice-subtitle, .wpeo-notice.notice-success a { + color: #47e58e; +} + +.tns-outer { + position: relative; +} + +.tns-outer .tns-nav { + text-align: center; + position: absolute; + width: 100%; + bottom: 0.5em; + z-index: 50; +} +.tns-outer .tns-nav button { + display: inline-block; + margin: 0 4px; + padding: 0; + width: 15px; + height: 15px; + background: #fff; + border-radius: 50%; + -webkit-box-shadow: 0px 1px 6px 0px rgba(0, 0, 0, 0.2); + box-shadow: 0px 1px 6px 0px rgba(0, 0, 0, 0.2); + -webkit-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; + border: 2px solid #fff; +} +.tns-outer .tns-nav button:hover { + -webkit-box-shadow: none; + box-shadow: none; +} +.tns-outer .tns-nav button.tns-nav-active { + border: 2px solid #0d8aff; + -webkit-box-shadow: 0px 0px 0px 2px #0d8aff; + box-shadow: 0px 0px 0px 2px #0d8aff; +} + +.tns-outer .tns-controls button[data-controls=prev], .tns-outer .tns-controls button[data-controls=next] { + position: absolute; + top: 50%; + -webkit-transform: translateY(-50%); + transform: translateY(-50%); + background: none; + padding: 0; + border: 0; + z-index: 60; +} +.tns-outer .tns-controls button[data-controls=prev] .icon, .tns-outer .tns-controls button[data-controls=next] .icon { + color: #3a3a3a; + background: #fff; + border-radius: 50%; + width: 28px; + height: 28px; + text-align: center; + line-height: 28px; + opacity: 0.7; + -webkit-transition: opacity 0.3s cubic-bezier(0.77, 0, 0.175, 1); + transition: opacity 0.3s cubic-bezier(0.77, 0, 0.175, 1); +} +.tns-outer .tns-controls button[data-controls=prev]:hover, .tns-outer .tns-controls button[data-controls=next]:hover { + -webkit-box-shadow: none; + box-shadow: none; +} +.tns-outer .tns-controls button[data-controls=prev]:hover .icon, .tns-outer .tns-controls button[data-controls=next]:hover .icon { + opacity: 1; +} +.tns-outer .tns-controls button[data-controls=prev]:active .icon, .tns-outer .tns-controls button[data-controls=next]:active .icon { + -webkit-transform: translateY(2px); + transform: translateY(2px); +} +.tns-outer .tns-controls button[data-controls=prev][disabled] .icon, .tns-outer .tns-controls button[data-controls=next][disabled] .icon { + opacity: 0.2; +} +.tns-outer .tns-controls button[data-controls=prev][disabled]:active .icon, .tns-outer .tns-controls button[data-controls=next][disabled]:active .icon { + -webkit-transform: none; + transform: none; +} +.tns-outer .tns-controls button[data-controls=prev] { + left: 15px; +} +.tns-outer .tns-controls button[data-controls=next] { + right: 15px; +} + +/*-------------------------------------------------------------- + Module : Form + Version : 1.0.0 + --------------------------------------------------------------*/ +/** Reset des champs de base */ +.wpeo-form input, .wpeo-form textarea, .wpeo-form select { + border: 1px solid rgba(0, 0, 0, 0.2); + font-size: 14px; + background: transparent; + padding: 0; + margin: 0; + width: 100%; + padding: 1em 0.5em; + -webkit-box-shadow: none; + box-shadow: none; +} +.wpeo-form input:focus, .wpeo-form input:active, .wpeo-form textarea:focus, .wpeo-form textarea:active, .wpeo-form select:focus, .wpeo-form select:active { + outline: none; + -webkit-box-shadow: none; + box-shadow: none; +} +.wpeo-form select { + padding: 1em 0; +} +.wpeo-form input[type=submit] { + width: auto; +} + +/** compatibilité Date */ +.wpeo-form .group-date .mysql-date { + display: none; +} + +/* Compatibility Dropdown */ +.wpeo-form .wpeo-dropdown { + display: block; + width: 100%; +} +.wpeo-form .wpeo-dropdown .dropdown-toggle { + width: 100%; + display: block; + -webkit-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; + border: 0; + font-size: 14px; + padding: 1em 2em 1em 1em; + margin: 0; +} +.wpeo-form .wpeo-dropdown .dropdown-toggle:hover { + cursor: pointer; +} +.wpeo-form .wpeo-dropdown .dropdown-toggle > .svg-inline--fa { + position: absolute; + right: 1em; + top: 50%; + -webkit-transform: translateY(-50%); + transform: translateY(-50%); +} + +.wpeo-form .form-element.disable .dropdown-toggle > .svg-inline--fa { + display: none; +} + +/* Compatibility Autocomplete */ +.wpeo-form .wpeo-autocomplete { + display: block; + width: 100%; +} +.wpeo-form .wpeo-autocomplete .autocomplete-label { + -webkit-box-shadow: none; + box-shadow: none; + padding: 0.74em 1em; +} + +.wpeo-form.form-light .wpeo-autocomplete .autocomplete-label { + background: #fff; +} +.wpeo-form.form-light .wpeo-autocomplete .autocomplete-label:hover { + background: #ececec; +} + +/** Général */ +.wpeo-form .form-element input[type=radio].form-field { + display: inline-block; + width: auto; +} + +/** Design */ +.wpeo-form .form-element input[type=radio].form-field { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + border-radius: 50%; + width: 16px; + height: 16px; + padding: 0; + border: 0; + background: transparent !important; + border: 1px solid rgba(0, 0, 0, 0.4); + -webkit-transition: 0.2s all linear; + transition: 0.2s all linear; + outline: none; + position: relative; + top: 2px; +} +.wpeo-form .form-element input[type=radio].form-field::before { + display: none !important; + content: "" !important; +} +.wpeo-form .form-element input[type=radio].form-field:hover { + cursor: pointer; + border: 1px solid #0d8aff; + -webkit-box-shadow: 0 0 0 1px #0d8aff inset; + box-shadow: 0 0 0 1px #0d8aff inset; + background: transparent !important; +} +.wpeo-form .form-element input[type=radio].form-field:checked { + border: 1px solid #0d8aff; + -webkit-box-shadow: 0 0 0 4px #0d8aff inset; + box-shadow: 0 0 0 4px #0d8aff inset; +} +.wpeo-form .form-element input[type=radio].form-field + label { + text-transform: none; + font-weight: 400; + font-size: 14px; + display: inline-block; + margin-right: 1em; +} +.wpeo-form .form-element input[type=radio].form-field + label:hover { + cursor: pointer; +} +.wpeo-form .form-element input[type=radio].form-field + label:active { + outline: none; +} + +/** Général */ +.wpeo-form .form-element input[type=checkbox].form-field { + display: inline-block; + width: auto; +} + +/** Design */ +.wpeo-form .form-element input[type=checkbox].form-field { + width: auto; + visibility: hidden; + display: none; +} +.wpeo-form .form-element input[type=checkbox].form-field + label { + text-transform: none; + font-weight: 400; + font-size: 14px; + display: inline-block; + margin-right: 1em; + position: relative; +} +.wpeo-form .form-element input[type=checkbox].form-field + label:hover { + cursor: pointer; +} +.wpeo-form .form-element input[type=checkbox].form-field + label:active { + outline: none; +} +.wpeo-form .form-element input[type=checkbox].form-field + label::before { + display: inline-block; + content: ""; + width: 14px; + height: 14px; + background: transparent; + -webkit-box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.4); + box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.4); + border: 2px solid #fff; + -webkit-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; + margin-right: 0.6em; +} +.wpeo-form .form-element input[type=checkbox].form-field:not(:checked) + label:hover::before { + -webkit-box-shadow: 0 0 0 2px #0d8aff; + box-shadow: 0 0 0 2px #0d8aff; +} +.wpeo-form .form-element input[type=checkbox].form-field:checked + label::before { + -webkit-box-shadow: 0 0 0 2px #0d8aff; + box-shadow: 0 0 0 2px #0d8aff; + background: #0d8aff; +} + +/** Formulaire design */ +.wpeo-form .form-element { + width: 100%; +} +.wpeo-form .form-element .form-label { + display: block; + font-size: 14px; + font-weight: 600; + margin: 0.6em 0; + color: rgba(0, 0, 0, 0.9); +} +.wpeo-form .form-element .form-field-container { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-flow: row wrap; + flex-flow: row wrap; + -webkit-box-flex: 0; + -ms-flex: 0 1 auto; + flex: 0 1 auto; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; +} +.wpeo-form .form-element .form-field-container:hover { + -webkit-box-shadow: none; + box-shadow: none; +} +.wpeo-form .form-element .form-field { + -webkit-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; + border-radius: 0; +} +.wpeo-form .form-element .form-field:hover { + -webkit-box-shadow: none; + box-shadow: none; +} +.wpeo-form .form-element .form-sublabel { + font-size: 12px; + font-style: italic; + color: rgba(0, 0, 0, 0.6); +} + +/** Alignement */ +.wpeo-form .form-element .form-field-inline { + margin-right: 0.4em; +} +.wpeo-form .form-element.form-align-vertical .form-field-container { + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; +} +.wpeo-form .form-element.form-align-horizontal .form-field-container { + -ms-flex-wrap: wrap; + flex-wrap: wrap; +} + +/** Couleur */ +.wpeo-form .form-element .form-field-container .form-field, .wpeo-form .form-element .form-field-container [class*=form-field-icon] { + background: #ececec; +} +.wpeo-form .form-element .form-field-container:hover .form-field, .wpeo-form .form-element .form-field-container:hover [class*=form-field-icon] { + background: #dfdfdf; +} +.wpeo-form .form-element [class*=form-field-label] { + background: #dfdfdf; +} + +.wpeo-form.form-light .form-element .form-field-container .form-field, .wpeo-form.form-light .form-element .form-field-container [class*=form-field-icon] { + background: #fff; +} +.wpeo-form.form-light .form-element .form-field-container:hover .form-field, .wpeo-form.form-light .form-element .form-field-container:hover [class*=form-field-icon] { + background: #ececec; +} +.wpeo-form.form-light .form-element [class*=form-field-label] { + background: #ececec; +} + +/** Icone */ +.wpeo-form .form-element [class*=form-field-icon] { + padding: 0.8em 0 0.8em 0.8em; + color: rgba(0, 0, 0, 0.4); + font-size: 16px; + -webkit-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; +} +.wpeo-form .form-element [class*=form-field-icon] [class*=fa] { + vertical-align: middle; +} +.wpeo-form .form-element .form-field-icon-prev { + padding: 0.8em 0 0.8em 0.8em; +} +.wpeo-form .form-element .form-field-icon-next { + padding: 0.8em 0.8em 0.8em 0; +} + +/** Previous & next label */ +.wpeo-form .form-element [class*=form-field-label] { + padding: 1.2em 1em; + font-size: 12px; +} +.wpeo-form .form-element .form-field-label-prev { + border-right: 1px solid rgba(0, 0, 0, 0.1); +} +.wpeo-form .form-element .form-field-label-next { + border-left: 1px solid rgba(0, 0, 0, 0.1); +} + +/** Required */ +.wpeo-form .form-element.form-element-required .form-label::after { + display: inline-block; + content: "*"; + color: #e05353; + padding: 0 0.4em; +} + +/** Erreur sur un champs */ +.wpeo-form .form-element.form-element-error .form-field-container { + border: 1px solid #e05353; +} + +/** Champs disabled */ +.wpeo-form .form-element.form-element-disable .form-field-container { + opacity: 0.6; + pointer-events: none; +} + +/* Simple */ +/* Moderne */ +.digirisk-signature-container { + max-width: 800px; + background: #fff; + -webkit-box-shadow: 0 0 40px 0 rgba(0, 0, 0, 0.1); + box-shadow: 0 0 40px 0 rgba(0, 0, 0, 0.1); + margin: 1.5em auto 0 auto; + padding: 2em; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} +.digirisk-signature-container * { + -webkit-box-sizing: border-box; + box-sizing: border-box; +} +.digirisk-signature-container .signature .signature-element .wpeo-button.modal-signature-open { + display: none; +} +.digirisk-signature-container .signature .signature-element img { + width: 100%; + height: auto; + border: 1px solid rgba(0, 0, 0, 0.4) !important; +} + +/** Cell header */ +.table-cell-header { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + margin-bottom: 0.5em; +} +.table-cell-header > * { + margin: auto 0; +} +.table-cell-header .wpeo-button { + margin: 0; +} + +.riskassessment-tasks .riskassessment-task-container, .riskassessment-task-container { + min-width: 430px; + border: 1px solid rgba(0, 0, 0, 0.1); + background: rgba(0, 0, 0, 0.05); + padding: 0.5em; +} + +.riskassessment-tasks { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} +.riskassessment-tasks .riskassessment-task-container { + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} +.riskassessment-tasks .riskassessment-task-add-wrapper { + min-width: calc(40px + 0.5em); + margin: auto 0; + text-align: center; +} + +.riskassessment-task-listing-wrapper .riskassessment-task-container { + margin-bottom: 0.5em; +} + +.riskassessment-task-container .riskassessment-task-single { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} +.riskassessment-task-container .riskassessment-task-single * { + -webkit-box-sizing: border-box; + box-sizing: border-box; +} +.riskassessment-task-container .riskassessment-task-single > * { + margin-top: auto; + margin-bottom: auto; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content { + width: 100%; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-author { + display: inline-block; + width: 25px; + min-width: 25px; + height: 25px; + line-height: 25px; + background: rgba(0, 0, 0, 0.5); + overflow: hidden; + text-transform: uppercase; + font-size: 14px; + font-weight: 600; + border-radius: 50%; + vertical-align: sub; + text-align: center; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-author a { + color: #fff !important; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-author-label { + word-break: break-all; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + font-size: 14px; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data > * { + margin: auto 0.2em; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-reference { + color: #263C5C; + font-weight: 600; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-reference:hover { + text-decoration: underline; + cursor: pointer; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-count { + background: rgba(0, 0, 0, 0.2); + font-size: 12px; + border-radius: 4px; + padding: 0.2em 0.4em; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress { + background: rgba(0, 0, 0, 0.2); + font-size: 12px; + border-radius: 4px; + padding: 0.2em 0.4em; + font-weight: 700; + color: rgba(0, 0, 0, 0.6); +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-0 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-1 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-2 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-3 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-4 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-5 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-6 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-7 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-8 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-9 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-10 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-11 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-12 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-13 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-14 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-15 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-16 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-17 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-18 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-19 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-20 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-21 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-22 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-23 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-24 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-25 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-26 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-27 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-28 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-29 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-30 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-31 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-32 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-33 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-34 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-35 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-36 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-37 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-38 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-39 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-40 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-41 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-42 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-43 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-44 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-45 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-46 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-47 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-48 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-49 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-50 { + background: #e05353; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-51 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-52 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-53 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-54 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-55 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-56 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-57 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-58 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-59 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-60 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-61 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-62 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-63 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-64 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-65 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-66 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-67 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-68 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-69 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-70 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-71 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-72 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-73 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-74 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-75 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-76 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-77 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-78 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-79 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-80 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-81 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-82 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-83 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-84 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-85 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-86 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-87 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-88 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-89 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-90 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-91 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-92 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-93 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-94 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-95 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-96 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-97 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-98 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-99 { + background: #e9ad4f; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-100 { + background: #47e58e; + color: #fff; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-title { + display: -webkit-box; + display: -ms-flexbox; + display: flex; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-title .riskassessment-task-progress-checkbox { + margin: auto 0; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-title .riskassessment-task-progress-checkbox input { + width: 20px; + height: 20px; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-add { + min-width: 40px; + margin-left: 0.5em; +} +.riskassessment-task-container .riskassessment-task-single .riskassessment-task-delete { + margin-right: -0.5em; +} + +.riskassessment-task-listing-wrapper { + width: 100%; +} + +.riskassessment-task-add { + margin: 5px; +} + +.riskassessment-task-list { + margin: 5px; +} + +/** Add comment in modal */ +.riskassessment-task-timespent-add-container { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + background: rgba(0, 0, 0, 0.1); + padding: 10px; + margin-bottom: 25px; +} +.riskassessment-task-timespent-add-container > * { + margin: auto 5px; +} +.riskassessment-task-timespent-add-container .timespent-comment { + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} +.riskassessment-task-timespent-add-container .timespent-date { + min-width: 250px; +} +.riskassessment-task-timespent-add-container .timespent-duration { + max-width: 100px; +} +.riskassessment-task-timespent-add-container .timespent-add-button { + min-width: 30px; +} +.riskassessment-task-timespent-add-container .timespent-add-button .wpeo-button { + margin-top: 20px; +} + +/** List of comments */ +.riskassessment-task-timespent-container .riskassessment-task .riskassessment-task-container { + background: #fff; + border: 0; +} + +.wpeo-modal[class*=modal-riskassessment-task] .modal-container .title { + display: block; + font-weight: 600; + font-size: 13px; + margin-bottom: 0.6em; + color: rgba(0, 0, 0, 0.8); +} +.wpeo-modal[class*=modal-riskassessment-task] .modal-container .title required { + font-size: 18px; + color: #0d8aff; + vertical-align: text-top; + line-height: 0.9; +} +.wpeo-modal[class*=modal-riskassessment-task] .modal-container .section-title { + font-size: 16px; + color: rgba(0, 0, 0, 0.8); + font-weight: 600; + margin-bottom: 0.6em; + display: block; +} +.wpeo-modal[class*=modal-riskassessment-task] .modal-container .riskassessment-task-single { + display: block !important; +} + +.wpeo-modal[class*=modal-riskassessment-task] .modal-container .riskassessment-task-container { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + padding-bottom: 1em; + margin-bottom: 1em; + border-bottom: 1px solid rgba(0, 0, 0, 0.2); +} +.wpeo-modal[class*=modal-riskassessment-task] .modal-container .riskassessment-task-container .riskassessment-task { + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; +} +.wpeo-modal[class*=modal-riskassessment-task] .modal-container .riskassessment-task-container .riskassessment-task input { + width: 100%; +} + +/** Listing */ +.wpeo-modal .modal-container .riskassessment-task-list .riskassessment-task > .riskassessment-task-container { + display: -webkit-box; + display: -ms-flexbox; + display: flex; +} +.wpeo-modal .modal-container .riskassessment-task-list .riskassessment-task > .riskassessment-task-container .riskassessment-task-single { + width: 100%; +} +.wpeo-modal .modal-container .riskassessment-task-list .riskassessment-task > .riskassessment-task-container .riskassessment-task-actions { + margin-left: auto; +} + +.wpeo-modal.modal-photo.modal-active { + z-index: 2014; +} +.wpeo-modal.modal-photo .clickable-photo { + border: 5px solid #fff; + -webkit-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; + width: 100%; +} +.wpeo-modal.modal-photo .clickable-photo:hover { + cursor: pointer; +} +.wpeo-modal.modal-photo .clickable-photo:hover .photo-image .photo { + opacity: 0.8; +} +.wpeo-modal.modal-photo .clickable-photo .photo-image { + position: relative; + width: 100%; + max-width: 120px; + height: 120px; + margin: auto; +} +.wpeo-modal.modal-photo .clickable-photo .photo-image .photo { + position: absolute; + top: 0; + left: 0; + width: 100%; + -o-object-fit: cover; + object-fit: cover; + max-width: none !important; + -webkit-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; +} +.wpeo-modal.modal-photo .clickable-photo .photo-image .clicked-photo-preview { + position: absolute; + display: inline-block; + top: 1em; + right: 1em; + z-index: 900; + height: 25px; + line-height: 25px; + background: #fff; + color: #0d8aff; + -webkit-transition: all 0.2s ease-out; + transition: all 0.2s ease-out; +} +.wpeo-modal.modal-photo .clickable-photo .photo-image .clicked-photo-preview:hover { + -webkit-transform: scale(1.1); + transform: scale(1.1); +} +.wpeo-modal.modal-photo .clickable-photo .photo-image .clicked-photo-preview i { + line-height: 25px; + font-size: 14px; +} +.wpeo-modal.modal-photo .clickable-photo .title { + word-break: break-all; +} + +.wpeo-modal.modal-photo .formattachnewfile { + padding-bottom: 0.5em; +} +.wpeo-modal.modal-photo input[type=file] { + border-bottom: 0 !important; +} + +.wpeo-modal .modal-container ul, .wpeo-modal .modal-container li { + margin: 0; + list-style-type: none; + padding: 0; +} + +@media (max-width: 1200px) { + td > .riskassessment-task-container { + min-width: 0; + } +} +.imgTabTitle { + max-height: 32px; + vertical-align: middle; +} diff --git a/css/dolisirh.min.css b/css/dolisirh.min.css new file mode 100644 index 0000000..53ce754 --- /dev/null +++ b/css/dolisirh.min.css @@ -0,0 +1 @@ +.wpeo-modal .title{display:block;font-weight:600;font-size:13px;margin-bottom:.6em;color:rgba(0,0,0,.8)}.wpeo-modal input[type=text],.wpeo-modal input[type=email],.wpeo-modal input[type=url],.wpeo-modal input[type=password],.wpeo-modal input[type=search],.wpeo-modal input[type=number],.wpeo-modal input[type=tel],.wpeo-modal input[type=range],.wpeo-modal input[type=date],.wpeo-modal input[type=month],.wpeo-modal input[type=week],.wpeo-modal input[type=time],.wpeo-modal input[type=datetime],.wpeo-modal input[type=datetime-local],.wpeo-modal input[type=color],.wpeo-modal select,.wpeo-modal textarea{width:100%;border:1px solid rgba(0,0,0,.2);padding:1em}.wpeo-modal input[type=text]:focus,.wpeo-modal input[type=email]:focus,.wpeo-modal input[type=url]:focus,.wpeo-modal input[type=password]:focus,.wpeo-modal input[type=search]:focus,.wpeo-modal input[type=number]:focus,.wpeo-modal input[type=tel]:focus,.wpeo-modal input[type=range]:focus,.wpeo-modal input[type=date]:focus,.wpeo-modal input[type=month]:focus,.wpeo-modal input[type=week]:focus,.wpeo-modal input[type=time]:focus,.wpeo-modal input[type=datetime]:focus,.wpeo-modal input[type=datetime-local]:focus,.wpeo-modal input[type=color]:focus,.wpeo-modal select:focus,.wpeo-modal textarea:focus{border:1px solid rgba(0,0,0,.6)}.wpeo-modal select{padding:1em 0}.form-label-required::after{display:inline-block;content:"*";color:#e05353;font-size:22px;line-height:0;position:relative;top:4px;left:4px}.pictoDoliSIRH{vertical-align:middle;width:24px;margin-right:2px}.wpeo-dropdown{position:relative;display:inline-block}.wpeo-dropdown .dropdown-toggle{display:inline-block}.wpeo-dropdown .dropdown-toggle span~*[class*=icon]{margin-left:10px}.wpeo-dropdown .dropdown-content{opacity:0;pointer-events:none;-webkit-transform:translateY(-10px);transform:translateY(-10px);-webkit-transition:all .2s ease-out;transition:all .2s ease-out;position:absolute;background:#fff;z-index:99;border:1px solid rgba(0,0,0,.1);-webkit-box-shadow:0 0 10px 0px rgba(0,0,0,.3);box-shadow:0 0 10px 0px rgba(0,0,0,.3);width:220px;padding:.6em}.wpeo-dropdown.dropdown-active .dropdown-content{opacity:1;pointer-events:auto;-webkit-transform:translateY(0);transform:translateY(0)}.wpeo-dropdown ul,.wpeo-dropdown li{margin:0;list-style-type:none;padding:0}.wpeo-dropdown .dropdown-item{display:block;color:rgba(0,0,0,.7);text-decoration:none}.wpeo-dropdown .dropdown-item::before{display:none;content:""}.wpeo-dropdown .dropdown-item .dropdown-result-title,.wpeo-dropdown .dropdown-item .dropdown-result-subtitle{display:block}.wpeo-dropdown .dropdown-item .dropdown-result-title{font-size:14px}.wpeo-dropdown .dropdown-item .dropdown-result-subtitle{font-size:12px;color:rgba(0,0,0,.5)}.wpeo-dropdown.dropdown-small .dropdown-content{width:60px}.wpeo-dropdown.dropdown-medium .dropdown-content{width:220px}.wpeo-dropdown.dropdown-large .dropdown-content{width:360px}.wpeo-dropdown.dropdown-padding-0 .dropdown-content{padding:0}.wpeo-dropdown.dropdown-padding-1 .dropdown-content{padding:.6em}.wpeo-dropdown.dropdown-padding-2 .dropdown-content{padding:1.2em}.wpeo-dropdown.dropdown-left .dropdown-content{left:0}.wpeo-dropdown.dropdown-right .dropdown-content{right:0}.wpeo-dropdown.dropdown-horizontal.dropdown-left .dropdown-content{left:100%}.wpeo-dropdown.dropdown-horizontal.dropdown-right .dropdown-content{right:100%}.wpeo-dropdown.dropdown-horizontal .dropdown-content{top:0;width:auto !important;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.wpeo-dropdown .dropdown-item.dropdown-item-disable{opacity:.6;cursor:default !important;pointer-events:none}.wpeo-dropdown .dropdown-content .dropdown-item{padding:.6em;background:#fff;-webkit-transition:all .2s ease-out;transition:all .2s ease-out}.wpeo-dropdown .dropdown-content .dropdown-item:hover{cursor:pointer;background:rgba(0,0,0,.1)}.wpeo-dropdown.dropdown-list .dropdown-content{text-align:left}.wpeo-dropdown.dropdown-list .dropdown-item::after{display:block;content:"";clear:both}.wpeo-dropdown.dropdown-list .dropdown-item img{float:left;margin-right:.4em}.wpeo-dropdown.dropdown-grid .dropdown-item img{width:100%;height:auto;display:block;margin:0}.wpeo-button{display:inline-block;border:0;-webkit-box-shadow:none;box-shadow:none;background:none;text-decoration:none;padding:6px 14px;line-height:1.4;vertical-align:middle;height:auto;border-radius:0;-webkit-transition:all .2s ease-out;transition:all .2s ease-out;position:relative;border-width:3px;border-style:solid;font-size:16px;-webkit-box-sizing:border-box;box-sizing:border-box;background:#0d8aff;border-color:#0d8aff;color:#fff}.wpeo-button:focus,.wpeo-button:visited{color:#fff}.wpeo-button:hover{color:#fff;-webkit-box-shadow:inset 0 -2.6em rgba(255,255,255,.25);box-shadow:inset 0 -2.6em rgba(255,255,255,.25);cursor:pointer;text-decoration:none}.wpeo-button:focus,.wpeo-button:active{outline:none}.wpeo-button{background:#0d8aff;border-color:#0d8aff;color:#fff}.wpeo-button.button-main{background:#0d8aff;border-color:#0d8aff;color:#fff}.wpeo-button.button-secondary{background:#263c5c;border-color:#263c5c;color:#fff}.wpeo-button.button-light{background:#fff;border-color:#fff;color:#333}.wpeo-button.button-light:hover{-webkit-box-shadow:inset 0 -2.6em rgba(0,0,0,.1);box-shadow:inset 0 -2.6em rgba(0,0,0,.1);color:#333}.wpeo-button.button-dark{background:#2b2b2b;border-color:#2b2b2b}.wpeo-button.button-grey{background:#ececec;border-color:#ececec;color:#333}.wpeo-button.button-grey:hover{-webkit-box-shadow:inset 0 -2.6em rgba(0,0,0,.1);box-shadow:inset 0 -2.6em rgba(0,0,0,.1);color:#333}.wpeo-button.button-red{background:#e05353;border-color:#e05353}.wpeo-button.button-yellow{background:#e9ad4f;border-color:#e9ad4f}.wpeo-button.button-blue{background:#0d8aff;border-color:#0d8aff}.wpeo-button.button-green{background:#47e58e;border-color:#47e58e}.wpeo-button.button-transparent{background:rgba(0,0,0,0);border-color:rgba(0,0,0,0);color:rgba(51,51,51,.4)}.wpeo-button.button-transparent:hover{color:#333;-webkit-box-shadow:inset 0 -2.6em rgba(255,255,255,0);box-shadow:inset 0 -2.6em rgba(255,255,255,0)}.wpeo-button.button-bordered{background:none;border-color:#0d8aff;color:#0d8aff}.wpeo-button.button-bordered.button-main{border-color:#0d8aff;color:#0d8aff}.wpeo-button.button-bordered.button-main:hover{-webkit-box-shadow:inset 0 -2.6em #0d8aff;box-shadow:inset 0 -2.6em #0d8aff;color:#fff}.wpeo-button.button-bordered.button-light{border-color:#fff;color:#fff}.wpeo-button.button-bordered.button-light:hover{-webkit-box-shadow:inset 0 -2.6em #fff;box-shadow:inset 0 -2.6em #fff;color:#333}.wpeo-button.button-bordered.button-dark{border-color:#2b2b2b;color:#2b2b2b}.wpeo-button.button-bordered.button-dark:hover{-webkit-box-shadow:inset 0 -2.6em #2b2b2b;box-shadow:inset 0 -2.6em #2b2b2b}.wpeo-button.button-bordered.button-grey{border-color:#ececec;color:#a0a0a0}.wpeo-button.button-bordered.button-grey:hover{-webkit-box-shadow:inset 0 -2.6em #ececec;box-shadow:inset 0 -2.6em #ececec;color:#333}.wpeo-button.button-bordered.button-red{border-color:#e05353;color:#e05353}.wpeo-button.button-bordered.button-red:hover{-webkit-box-shadow:inset 0 -2.6em #e05353;box-shadow:inset 0 -2.6em #e05353}.wpeo-button.button-bordered.button-yellow{border-color:#e9ad4f;color:#e9ad4f}.wpeo-button.button-bordered.button-yellow:hover{-webkit-box-shadow:inset 0 -2.6em #e9ad4f;box-shadow:inset 0 -2.6em #e9ad4f}.wpeo-button.button-bordered.button-blue{border-color:#0d8aff;color:#0d8aff}.wpeo-button.button-bordered.button-blue:hover{-webkit-box-shadow:inset 0 -2.6em #0d8aff;box-shadow:inset 0 -2.6em #0d8aff}.wpeo-button.button-bordered.button-green{border-color:#47e58e;color:#47e58e}.wpeo-button.button-bordered.button-green:hover{-webkit-box-shadow:inset 0 -2.6em #47e58e;box-shadow:inset 0 -2.6em #47e58e}.wpeo-button.button-bordered:hover{-webkit-box-shadow:inset 0 -2.6em #0d8aff;box-shadow:inset 0 -2.6em #0d8aff;color:#fff}.wpeo-button .button-add{position:absolute;top:.4em;right:.2em;opacity:.6;font-size:14px;-webkit-transition:all .2s ease-out;transition:all .2s ease-out}.wpeo-button:hover .button-add{opacity:.8}.wpeo-button.button-square-40 .button-add{top:.1em;right:0}.wpeo-button .button-icon,.wpeo-button span{position:relative}.wpeo-button .button-icon~span{margin-left:10px}.wpeo-button span~.button-icon{margin-left:10px}.wpeo-button.button-strong span{font-weight:800}.wpeo-button.button-uppercase span{text-transform:uppercase;font-size:14px}.wpeo-button[class*=button-square-]{text-align:center;overflow:hidden;padding:0}.wpeo-button.button-square-30{width:30px;height:30px;line-height:24px}.wpeo-button.button-square-30 .button-icon{font-size:12px;line-height:24px}.wpeo-button.button-square-40{width:40px;height:40px;line-height:34px}.wpeo-button.button-square-40 .button-icon{line-height:34px}.wpeo-button.button-square-50{width:50px;height:50px;line-height:44px}.wpeo-button.button-square-50 .button-icon{line-height:44px}.wpeo-button.button-square-60{width:60px;height:60px;line-height:54px}.wpeo-button.button-square-60 .button-icon{line-height:54px}.wpeo-button.button-float-left{float:left}.wpeo-button.button-float-right{float:right}.wpeo-button.button-margin{margin:1em 0}.wpeo-button.button-radius-1{border-radius:2px}.wpeo-button.button-radius-2{border-radius:4px}.wpeo-button.button-radius-3{border-radius:6px}.wpeo-button.button-rounded{border-radius:50%}.wpeo-button.button-disable{background:#ececec !important;border-color:#ececec !important;color:rgba(0,0,0,.4) !important;pointer-events:none}.wpeo-button.button-disable:hover{-webkit-box-shadow:none !important;box-shadow:none !important}.wpeo-button.button-disable.button-event{pointer-events:all}.wpeo-button.button-size-small{font-size:14px}.wpeo-button.button-size-small.button-uppercase span{font-size:12px}.wpeo-button.button-size-large{font-size:18px}.wpeo-button.button-size-large.button-uppercase span{font-size:16px}.wpeo-modal{position:fixed;top:0;left:0;width:100%;height:100%;z-index:1000;background:rgba(39,42,53,.9);opacity:0;pointer-events:none;-webkit-transition:all .2s ease-out;transition:all .2s ease-out}.wpeo-modal textarea{resize:none}.wpeo-modal.modal-active{opacity:1;pointer-events:auto;z-index:1002}.wpeo-modal.modal-active .modal-container{-webkit-transform:translate(-50%, -50%);transform:translate(-50%, -50%)}.wpeo-modal.modal-active textarea{resize:both}.wpeo-modal.modal-active .modal-active{z-index:1003}.wpeo-modal.modal-active .modal-active .modal-active{z-index:1004}.wpeo-modal.modal-force-display .modal-close{display:none}.wpeo-modal .modal-container{position:absolute;-webkit-transition:all .2s ease-out;transition:all .2s ease-out;width:100%;max-width:860px;height:100%;max-height:560px;background:#fff;padding:1em 0;margin:auto;top:50%;left:50%;-webkit-transform:translate(-50%, -60%);transform:translate(-50%, -60%)}@media(max-width: 480px){.wpeo-modal .modal-container{padding:1em}}.wpeo-modal .modal-container .modal-header{height:10%;display:-webkit-box;display:-ms-flexbox;display:flex;padding:0 2em}.wpeo-modal .modal-container .modal-content{height:78%;padding:0 2em}.wpeo-modal .modal-container .modal-footer{height:12%;padding:0 2em}.wpeo-modal .modal-container .modal-header .modal-title,.wpeo-modal .modal-container .modal-header .modal-close{margin:auto 0}.wpeo-modal .modal-container .modal-header .modal-title{text-transform:uppercase;font-size:18px;white-space:normal}@media(max-width: 770px){.wpeo-modal .modal-container .modal-header .modal-title{font-size:16px}}@media(max-width: 480px){.wpeo-modal .modal-container .modal-header .modal-title{font-size:14px}}.wpeo-modal .modal-container .modal-header .modal-close{margin-left:auto;color:rgba(0,0,0,.3);padding:4px;-webkit-transition:all .2s ease-out;transition:all .2s ease-out}.wpeo-modal .modal-container .modal-header .modal-close:hover{cursor:pointer;color:#0d8aff}.wpeo-modal .modal-container .modal-content{overflow-y:auto;font-size:14px}@media(max-width: 480px){.wpeo-modal .modal-container .modal-content{font-size:12px}}.wpeo-modal .modal-container .modal-footer{text-align:right;padding-top:1em}.wpeo-modal .modal-container .modal-footer.left{text-align:left}.wpeo-modal .modal-container .modal-footer.center{text-align:center}.wpeo-loader{-webkit-transition:all .2s ease-out;transition:all .2s ease-out;pointer-events:none;opacity:.5;position:relative}.wpeo-loader .loader-spin{position:absolute;border:3px solid #a7a7a7;border-top:3px solid #002140;border-radius:50%;width:20px;height:20px;z-index:99;left:50%;top:50%;margin:0 !important;padding:0 !important;-webkit-animation:loader-spin 1s ease-out infinite;animation:loader-spin 1s ease-out infinite}@-webkit-keyframes loader-spin{0%{-webkit-transform:translate(-50%, -50%) rotate(0deg);transform:translate(-50%, -50%) rotate(0deg)}100%{-webkit-transform:translate(-50%, -50%) rotate(360deg);transform:translate(-50%, -50%) rotate(360deg)}}@keyframes loader-spin{0%{-webkit-transform:translate(-50%, -50%) rotate(0deg);transform:translate(-50%, -50%) rotate(0deg)}100%{-webkit-transform:translate(-50%, -50%) rotate(360deg);transform:translate(-50%, -50%) rotate(360deg)}}.wpeo-gridlayout{display:grid;grid-gap:1em 1em;grid-template-columns:repeat(4, 1fr)}.wpeo-gridlayout.grid-1{grid-template-columns:repeat(1, 1fr)}.wpeo-gridlayout.grid-1>.gridw-1{grid-column:auto/span 1}.wpeo-gridlayout.grid-2{grid-template-columns:repeat(2, 1fr)}.wpeo-gridlayout.grid-2>.gridw-1{grid-column:auto/span 1}.wpeo-gridlayout.grid-2>.gridw-2{grid-column:auto/span 2}@media(max-width: 770px){.wpeo-gridlayout.grid-2>.gridw-2{grid-column:auto/span 2}}.wpeo-gridlayout.grid-3{grid-template-columns:repeat(3, 1fr)}.wpeo-gridlayout.grid-3>.gridw-1{grid-column:auto/span 1}.wpeo-gridlayout.grid-3>.gridw-2{grid-column:auto/span 2}@media(max-width: 770px){.wpeo-gridlayout.grid-3>.gridw-2{grid-column:auto/span 2}}.wpeo-gridlayout.grid-3>.gridw-3{grid-column:auto/span 3}@media(max-width: 770px){.wpeo-gridlayout.grid-3>.gridw-3{grid-column:auto/span 2}}.wpeo-gridlayout.grid-4{grid-template-columns:repeat(4, 1fr)}.wpeo-gridlayout.grid-4>.gridw-1{grid-column:auto/span 1}.wpeo-gridlayout.grid-4>.gridw-2{grid-column:auto/span 2}@media(max-width: 770px){.wpeo-gridlayout.grid-4>.gridw-2{grid-column:auto/span 2}}.wpeo-gridlayout.grid-4>.gridw-3{grid-column:auto/span 3}@media(max-width: 770px){.wpeo-gridlayout.grid-4>.gridw-3{grid-column:auto/span 2}}.wpeo-gridlayout.grid-4>.gridw-4{grid-column:auto/span 4}@media(max-width: 770px){.wpeo-gridlayout.grid-4>.gridw-4{grid-column:auto/span 2}}.wpeo-gridlayout.grid-5{grid-template-columns:repeat(5, 1fr)}.wpeo-gridlayout.grid-5>.gridw-1{grid-column:auto/span 1}.wpeo-gridlayout.grid-5>.gridw-2{grid-column:auto/span 2}@media(max-width: 770px){.wpeo-gridlayout.grid-5>.gridw-2{grid-column:auto/span 2}}.wpeo-gridlayout.grid-5>.gridw-3{grid-column:auto/span 3}@media(max-width: 770px){.wpeo-gridlayout.grid-5>.gridw-3{grid-column:auto/span 2}}.wpeo-gridlayout.grid-5>.gridw-4{grid-column:auto/span 4}@media(max-width: 770px){.wpeo-gridlayout.grid-5>.gridw-4{grid-column:auto/span 2}}.wpeo-gridlayout.grid-5>.gridw-5{grid-column:auto/span 5}@media(max-width: 770px){.wpeo-gridlayout.grid-5>.gridw-5{grid-column:auto/span 2}}.wpeo-gridlayout.grid-6{grid-template-columns:repeat(6, 1fr)}.wpeo-gridlayout.grid-6>.gridw-1{grid-column:auto/span 1}.wpeo-gridlayout.grid-6>.gridw-2{grid-column:auto/span 2}@media(max-width: 770px){.wpeo-gridlayout.grid-6>.gridw-2{grid-column:auto/span 2}}.wpeo-gridlayout.grid-6>.gridw-3{grid-column:auto/span 3}@media(max-width: 770px){.wpeo-gridlayout.grid-6>.gridw-3{grid-column:auto/span 2}}.wpeo-gridlayout.grid-6>.gridw-4{grid-column:auto/span 4}@media(max-width: 770px){.wpeo-gridlayout.grid-6>.gridw-4{grid-column:auto/span 2}}.wpeo-gridlayout.grid-6>.gridw-5{grid-column:auto/span 5}@media(max-width: 770px){.wpeo-gridlayout.grid-6>.gridw-5{grid-column:auto/span 2}}.wpeo-gridlayout.grid-6>.gridw-6{grid-column:auto/span 6}@media(max-width: 770px){.wpeo-gridlayout.grid-6>.gridw-6{grid-column:auto/span 2}}.wpeo-gridlayout>.gridh-1{grid-row:auto/span 1}@media(max-width: 770px){.wpeo-gridlayout>.gridh-1{grid-row:auto/span 1 !important}}.wpeo-gridlayout>.gridh-2{grid-row:auto/span 2}@media(max-width: 770px){.wpeo-gridlayout>.gridh-2{grid-row:auto/span 1 !important}}.wpeo-gridlayout>.gridh-3{grid-row:auto/span 3}@media(max-width: 770px){.wpeo-gridlayout>.gridh-3{grid-row:auto/span 1 !important}}.wpeo-gridlayout>.gridh-4{grid-row:auto/span 4}@media(max-width: 770px){.wpeo-gridlayout>.gridh-4{grid-row:auto/span 1 !important}}.wpeo-gridlayout>.gridh-5{grid-row:auto/span 5}@media(max-width: 770px){.wpeo-gridlayout>.gridh-5{grid-row:auto/span 1 !important}}.wpeo-gridlayout>.gridh-6{grid-row:auto/span 6}@media(max-width: 770px){.wpeo-gridlayout>.gridh-6{grid-row:auto/span 1 !important}}.wpeo-gridlayout.grid-margin-0{margin:0em 0}.wpeo-gridlayout.grid-margin-1{margin:1em 0}.wpeo-gridlayout.grid-margin-2{margin:2em 0}.wpeo-gridlayout.grid-margin-3{margin:3em 0}.wpeo-gridlayout.grid-margin-4{margin:4em 0}.wpeo-gridlayout.grid-margin-5{margin:5em 0}.wpeo-gridlayout.grid-margin-6{margin:6em 0}.wpeo-gridlayout.grid-gap-0{grid-gap:0em 0em}.wpeo-gridlayout.grid-gap-1{grid-gap:1em 1em}.wpeo-gridlayout.grid-gap-2{grid-gap:2em 2em}.wpeo-gridlayout.grid-gap-3{grid-gap:3em 3em}.wpeo-gridlayout.grid-gap-4{grid-gap:4em 4em}.wpeo-gridlayout.grid-gap-5{grid-gap:5em 5em}.wpeo-gridlayout.grid-gap-6{grid-gap:6em 6em}.wpeo-gridlayout .grid-align-center{margin-left:auto;margin-right:auto}.wpeo-gridlayout .grid-align-right{margin-left:auto}.wpeo-gridlayout .grid-align-middle{margin-top:auto;margin-bottom:auto}.wpeo-gridlayout .grid-align-bottom{margin-top:auto}@media(max-width: 480px){.wpeo-gridlayout:not(.dropdown-content).grid-2{grid-template-columns:repeat(1, 1fr) !important}}@media(max-width: 770px){.wpeo-gridlayout:not(.dropdown-content).grid-3{grid-template-columns:repeat(2, 1fr) !important}}@media(max-width: 480px){.wpeo-gridlayout:not(.dropdown-content).grid-3{grid-template-columns:repeat(1, 1fr) !important}}@media(max-width: 770px){.wpeo-gridlayout:not(.dropdown-content).grid-4{grid-template-columns:repeat(2, 1fr) !important}}@media(max-width: 480px){.wpeo-gridlayout:not(.dropdown-content).grid-4{grid-template-columns:repeat(1, 1fr) !important}}@media(max-width: 770px){.wpeo-gridlayout:not(.dropdown-content).grid-5{grid-template-columns:repeat(2, 1fr) !important}}@media(max-width: 480px){.wpeo-gridlayout:not(.dropdown-content).grid-5{grid-template-columns:repeat(1, 1fr) !important}}@media(max-width: 770px){.wpeo-gridlayout:not(.dropdown-content).grid-6{grid-template-columns:repeat(2, 1fr) !important}}@media(max-width: 480px){.wpeo-gridlayout:not(.dropdown-content).grid-6{grid-template-columns:repeat(1, 1fr) !important}}@media(max-width: 480px){.wpeo-gridlayout:not(.dropdown-content)>*{grid-column:auto/span 1 !important}}.wpeo-table.table-flex{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;font-size:14px}.wpeo-table.table-flex .table-row{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.wpeo-table.table-flex .table-row:not(.table-header):nth-of-type(odd){background:rgba(0,0,0,.05)}.wpeo-table.table-flex .table-row.table-header{background:#263c5c}.wpeo-table.table-flex .table-row.table-header .table-cell{font-weight:700;color:#fff}.wpeo-table.table-flex .table-cell{margin:auto 0;width:100%;padding:.8em .6em}@media(max-width: 770px){.wpeo-table.table-flex .table-cell{padding:.4em}}.wpeo-table.table-flex.table-1 .table-cell{width:100%}.wpeo-table.table-flex.table-2 .table-cell{width:50%}.wpeo-table.table-flex.table-3 .table-cell{width:33.3333333333%}.wpeo-table.table-flex.table-4 .table-cell{width:25%}.wpeo-table.table-flex.table-5 .table-cell{width:20%}.wpeo-table.table-flex.table-6 .table-cell{width:16.6666666667%}.wpeo-table.table-flex.table-7 .table-cell{width:14.2857142857%}.wpeo-table.table-flex.table-8 .table-cell{width:12.5%}.wpeo-table.table-flex.table-9 .table-cell{width:11.1111111111%}.wpeo-table.table-flex.table-10 .table-cell{width:10%}.wpeo-table.table-flex .table-cell.table-25{max-width:25px;min-width:25px}.wpeo-table.table-flex .table-cell.table-50{max-width:50px;min-width:50px}.wpeo-table.table-flex .table-cell.table-75{max-width:75px;min-width:75px}.wpeo-table.table-flex .table-cell.table-100{max-width:100px;min-width:100px}.wpeo-table.table-flex .table-cell.table-125{max-width:125px;min-width:125px}.wpeo-table.table-flex .table-cell.table-150{max-width:150px;min-width:150px}.wpeo-table.table-flex .table-cell.table-175{max-width:175px;min-width:175px}.wpeo-table.table-flex .table-cell.table-200{max-width:200px;min-width:200px}.wpeo-table.table-flex .table-cell.table-225{max-width:225px;min-width:225px}.wpeo-table.table-flex .table-cell.table-250{max-width:250px;min-width:250px}.wpeo-table.table-flex .table-cell.table-275{max-width:275px;min-width:275px}.wpeo-table.table-flex .table-cell.table-300{max-width:300px;min-width:300px}.wpeo-table.table-flex .table-cell.table-325{max-width:325px;min-width:325px}.wpeo-table.table-flex .table-cell.table-350{max-width:350px;min-width:350px}.wpeo-table.table-flex .table-cell.table-375{max-width:375px;min-width:375px}.wpeo-table.table-flex .table-cell.table-400{max-width:400px;min-width:400px}.wpeo-table.table-flex .table-cell.table-425{max-width:425px;min-width:425px}.wpeo-table.table-flex .table-cell.table-450{max-width:450px;min-width:450px}.wpeo-table.table-flex .table-cell.table-475{max-width:475px;min-width:475px}.wpeo-table.table-flex .table-cell.table-500{max-width:500px;min-width:500px}.wpeo-table.table-flex .table-cell.table-full{width:100%}.wpeo-table.table-flex .table-cell.table-end{text-align:right;margin-left:auto}.wpeo-table.table-flex .table-cell.table-padding-0{padding:0}@media(max-width: 480px){.wpeo-table.table-flex .table-row{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.wpeo-table.table-flex .table-cell{width:100%}}.wpeo-tooltip{display:block;position:absolute;bottom:0;left:0;opacity:0;pointer-events:none;z-index:99999;white-space:nowrap;background:#2b2b2b;color:#fff;border-radius:6px;font-size:.8rem;padding:0 1em;height:2.2em;line-height:2.2em}.wpeo-tooltip::before{display:block;content:"";width:0;height:0;border-style:solid;position:absolute}.wpeo-tooltip:focus{outline:none}.wpeo-tooltip.tooltip-dark{background:#2b2b2b}.wpeo-tooltip.tooltip-dark.tooltip-top::before{border-color:#2b2b2b rgba(0,0,0,0) rgba(0,0,0,0) rgba(0,0,0,0)}.wpeo-tooltip.tooltip-dark.tooltip-right::before{border-color:rgba(0,0,0,0) #2b2b2b rgba(0,0,0,0) rgba(0,0,0,0)}.wpeo-tooltip.tooltip-dark.tooltip-bottom::before{border-color:rgba(0,0,0,0) rgba(0,0,0,0) #2b2b2b rgba(0,0,0,0)}.wpeo-tooltip.tooltip-dark.tooltip-left::before{border-color:rgba(0,0,0,0) rgba(0,0,0,0) rgba(0,0,0,0) #2b2b2b}.wpeo-tooltip.tooltip-primary{background:#0d8aff}.wpeo-tooltip.tooltip-primary.tooltip-top::before{border-color:#0d8aff rgba(0,0,0,0) rgba(0,0,0,0) rgba(0,0,0,0)}.wpeo-tooltip.tooltip-primary.tooltip-right::before{border-color:rgba(0,0,0,0) #0d8aff rgba(0,0,0,0) rgba(0,0,0,0)}.wpeo-tooltip.tooltip-primary.tooltip-bottom::before{border-color:rgba(0,0,0,0) rgba(0,0,0,0) #0d8aff rgba(0,0,0,0)}.wpeo-tooltip.tooltip-primary.tooltip-left::before{border-color:rgba(0,0,0,0) rgba(0,0,0,0) rgba(0,0,0,0) #0d8aff}.wpeo-tooltip.tooltip-light{background:#ececec;color:rgba(0,0,0,.6)}.wpeo-tooltip.tooltip-light.tooltip-top::before{border-color:#ececec rgba(0,0,0,0) rgba(0,0,0,0) rgba(0,0,0,0)}.wpeo-tooltip.tooltip-light.tooltip-right::before{border-color:rgba(0,0,0,0) #ececec rgba(0,0,0,0) rgba(0,0,0,0)}.wpeo-tooltip.tooltip-light.tooltip-bottom::before{border-color:rgba(0,0,0,0) rgba(0,0,0,0) #ececec rgba(0,0,0,0)}.wpeo-tooltip.tooltip-light.tooltip-left::before{border-color:rgba(0,0,0,0) rgba(0,0,0,0) rgba(0,0,0,0) #ececec}.wpeo-tooltip.tooltip-red{background:#e05353}.wpeo-tooltip.tooltip-red.tooltip-top::before{border-color:#e05353 rgba(0,0,0,0) rgba(0,0,0,0) rgba(0,0,0,0)}.wpeo-tooltip.tooltip-red.tooltip-right::before{border-color:rgba(0,0,0,0) #e05353 rgba(0,0,0,0) rgba(0,0,0,0)}.wpeo-tooltip.tooltip-red.tooltip-bottom::before{border-color:rgba(0,0,0,0) rgba(0,0,0,0) #e05353 rgba(0,0,0,0)}.wpeo-tooltip.tooltip-red.tooltip-left::before{border-color:rgba(0,0,0,0) rgba(0,0,0,0) rgba(0,0,0,0) #e05353}.wpeo-tooltip.tooltip-top::before{border-width:6px 6px 0 6px;border-color:#2b2b2b rgba(0,0,0,0) rgba(0,0,0,0) rgba(0,0,0,0);bottom:-6px;left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.wpeo-tooltip.tooltip-right::before{border-width:6px 6px 6px 0;border-color:rgba(0,0,0,0) #2b2b2b rgba(0,0,0,0) rgba(0,0,0,0);top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);left:-6px}.wpeo-tooltip.tooltip-bottom::before{border-width:0 6px 6px 6px;border-color:rgba(0,0,0,0) rgba(0,0,0,0) #2b2b2b rgba(0,0,0,0);top:-6px;left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.wpeo-tooltip.tooltip-left::before{border-width:6px 0 6px 6px;border-color:rgba(0,0,0,0) rgba(0,0,0,0) rgba(0,0,0,0) #2b2b2b;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);right:-6px}.wpeo-notice{position:relative;font-size:1em;padding:1em;overflow:hidden;border-radius:3px;border:solid #eee 1px;margin:1em 0;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-transition:all .2s ease-out;transition:all .2s ease-out;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.wpeo-notice::before{display:block;font-family:"Font Awesome 5 Free";font-weight:900;font-size:24px}.wpeo-notice .notice-content{width:100%;padding:0 1em;color:rgba(0,0,0,.6)}.wpeo-notice .notice-title{font-size:20px;font-weight:600;color:rgba(0,0,0,.9)}.wpeo-notice .notice-subtitle{font-size:14px}.wpeo-notice .notice-close{color:rgba(0,0,0,.3);-webkit-transition:all .2s ease-out;transition:all .2s ease-out}.wpeo-notice .notice-close:hover{color:#0d8aff;cursor:pointer}.wpeo-notice ul{padding:0 0 0 1.4em;margin:.4em 0}.wpeo-notice.notice-info{border-left:solid #0d8aff 6px;color:#0d8aff;background:rgba(13,138,255,.05)}.wpeo-notice.notice-info::before{content:""}.wpeo-notice.notice-info .notice-title,.wpeo-notice.notice-info .notice-subtitle,.wpeo-notice.notice-info a{color:#0d8aff}.wpeo-notice.notice-error{border-left:solid #e05353 6px;color:#e05353;background:rgba(224,83,83,.05)}.wpeo-notice.notice-error::before{content:""}.wpeo-notice.notice-error .notice-title,.wpeo-notice.notice-error .notice-subtitle,.wpeo-notice.notice-error a{color:#e05353}.wpeo-notice.notice-warning{border-left:solid #e9ad4f 6px;color:#e9ad4f;background:rgba(233,173,79,.05)}.wpeo-notice.notice-warning::before{content:""}.wpeo-notice.notice-warning .notice-title,.wpeo-notice.notice-warning .notice-subtitle,.wpeo-notice.notice-warning a{color:#e9ad4f}.wpeo-notice.notice-success{border-left:solid #47e58e 6px;color:#47e58e;background:rgba(71,229,142,.05)}.wpeo-notice.notice-success::before{content:""}.wpeo-notice.notice-success .notice-title,.wpeo-notice.notice-success .notice-subtitle,.wpeo-notice.notice-success a{color:#47e58e}.tns-outer{position:relative}.tns-outer .tns-nav{text-align:center;position:absolute;width:100%;bottom:.5em;z-index:50}.tns-outer .tns-nav button{display:inline-block;margin:0 4px;padding:0;width:15px;height:15px;background:#fff;border-radius:50%;-webkit-box-shadow:0px 1px 6px 0px rgba(0,0,0,.2);box-shadow:0px 1px 6px 0px rgba(0,0,0,.2);-webkit-transition:all .2s ease-out;transition:all .2s ease-out;border:2px solid #fff}.tns-outer .tns-nav button:hover{-webkit-box-shadow:none;box-shadow:none}.tns-outer .tns-nav button.tns-nav-active{border:2px solid #0d8aff;-webkit-box-shadow:0px 0px 0px 2px #0d8aff;box-shadow:0px 0px 0px 2px #0d8aff}.tns-outer .tns-controls button[data-controls=prev],.tns-outer .tns-controls button[data-controls=next]{position:absolute;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);background:none;padding:0;border:0;z-index:60}.tns-outer .tns-controls button[data-controls=prev] .icon,.tns-outer .tns-controls button[data-controls=next] .icon{color:#3a3a3a;background:#fff;border-radius:50%;width:28px;height:28px;text-align:center;line-height:28px;opacity:.7;-webkit-transition:opacity .3s cubic-bezier(0.77, 0, 0.175, 1);transition:opacity .3s cubic-bezier(0.77, 0, 0.175, 1)}.tns-outer .tns-controls button[data-controls=prev]:hover,.tns-outer .tns-controls button[data-controls=next]:hover{-webkit-box-shadow:none;box-shadow:none}.tns-outer .tns-controls button[data-controls=prev]:hover .icon,.tns-outer .tns-controls button[data-controls=next]:hover .icon{opacity:1}.tns-outer .tns-controls button[data-controls=prev]:active .icon,.tns-outer .tns-controls button[data-controls=next]:active .icon{-webkit-transform:translateY(2px);transform:translateY(2px)}.tns-outer .tns-controls button[data-controls=prev][disabled] .icon,.tns-outer .tns-controls button[data-controls=next][disabled] .icon{opacity:.2}.tns-outer .tns-controls button[data-controls=prev][disabled]:active .icon,.tns-outer .tns-controls button[data-controls=next][disabled]:active .icon{-webkit-transform:none;transform:none}.tns-outer .tns-controls button[data-controls=prev]{left:15px}.tns-outer .tns-controls button[data-controls=next]{right:15px}.wpeo-form input,.wpeo-form textarea,.wpeo-form select{border:1px solid rgba(0,0,0,.2);font-size:14px;background:rgba(0,0,0,0);padding:0;margin:0;width:100%;padding:1em .5em;-webkit-box-shadow:none;box-shadow:none}.wpeo-form input:focus,.wpeo-form input:active,.wpeo-form textarea:focus,.wpeo-form textarea:active,.wpeo-form select:focus,.wpeo-form select:active{outline:none;-webkit-box-shadow:none;box-shadow:none}.wpeo-form select{padding:1em 0}.wpeo-form input[type=submit]{width:auto}.wpeo-form .group-date .mysql-date{display:none}.wpeo-form .wpeo-dropdown{display:block;width:100%}.wpeo-form .wpeo-dropdown .dropdown-toggle{width:100%;display:block;-webkit-transition:all .2s ease-out;transition:all .2s ease-out;border:0;font-size:14px;padding:1em 2em 1em 1em;margin:0}.wpeo-form .wpeo-dropdown .dropdown-toggle:hover{cursor:pointer}.wpeo-form .wpeo-dropdown .dropdown-toggle>.svg-inline--fa{position:absolute;right:1em;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.wpeo-form .form-element.disable .dropdown-toggle>.svg-inline--fa{display:none}.wpeo-form .wpeo-autocomplete{display:block;width:100%}.wpeo-form .wpeo-autocomplete .autocomplete-label{-webkit-box-shadow:none;box-shadow:none;padding:.74em 1em}.wpeo-form.form-light .wpeo-autocomplete .autocomplete-label{background:#fff}.wpeo-form.form-light .wpeo-autocomplete .autocomplete-label:hover{background:#ececec}.wpeo-form .form-element input[type=radio].form-field{display:inline-block;width:auto}.wpeo-form .form-element input[type=radio].form-field{-webkit-appearance:none;-moz-appearance:none;appearance:none;border-radius:50%;width:16px;height:16px;padding:0;border:0;background:rgba(0,0,0,0) !important;border:1px solid rgba(0,0,0,.4);-webkit-transition:.2s all linear;transition:.2s all linear;outline:none;position:relative;top:2px}.wpeo-form .form-element input[type=radio].form-field::before{display:none !important;content:"" !important}.wpeo-form .form-element input[type=radio].form-field:hover{cursor:pointer;border:1px solid #0d8aff;-webkit-box-shadow:0 0 0 1px #0d8aff inset;box-shadow:0 0 0 1px #0d8aff inset;background:rgba(0,0,0,0) !important}.wpeo-form .form-element input[type=radio].form-field:checked{border:1px solid #0d8aff;-webkit-box-shadow:0 0 0 4px #0d8aff inset;box-shadow:0 0 0 4px #0d8aff inset}.wpeo-form .form-element input[type=radio].form-field+label{text-transform:none;font-weight:400;font-size:14px;display:inline-block;margin-right:1em}.wpeo-form .form-element input[type=radio].form-field+label:hover{cursor:pointer}.wpeo-form .form-element input[type=radio].form-field+label:active{outline:none}.wpeo-form .form-element input[type=checkbox].form-field{display:inline-block;width:auto}.wpeo-form .form-element input[type=checkbox].form-field{width:auto;visibility:hidden;display:none}.wpeo-form .form-element input[type=checkbox].form-field+label{text-transform:none;font-weight:400;font-size:14px;display:inline-block;margin-right:1em;position:relative}.wpeo-form .form-element input[type=checkbox].form-field+label:hover{cursor:pointer}.wpeo-form .form-element input[type=checkbox].form-field+label:active{outline:none}.wpeo-form .form-element input[type=checkbox].form-field+label::before{display:inline-block;content:"";width:14px;height:14px;background:rgba(0,0,0,0);-webkit-box-shadow:0 0 0 1px rgba(0,0,0,.4);box-shadow:0 0 0 1px rgba(0,0,0,.4);border:2px solid #fff;-webkit-transition:all .2s ease-out;transition:all .2s ease-out;margin-right:.6em}.wpeo-form .form-element input[type=checkbox].form-field:not(:checked)+label:hover::before{-webkit-box-shadow:0 0 0 2px #0d8aff;box-shadow:0 0 0 2px #0d8aff}.wpeo-form .form-element input[type=checkbox].form-field:checked+label::before{-webkit-box-shadow:0 0 0 2px #0d8aff;box-shadow:0 0 0 2px #0d8aff;background:#0d8aff}.wpeo-form .form-element{width:100%}.wpeo-form .form-element .form-label{display:block;font-size:14px;font-weight:600;margin:.6em 0;color:rgba(0,0,0,.9)}.wpeo-form .form-element .form-field-container{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-box-flex:0;-ms-flex:0 1 auto;flex:0 1 auto;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.wpeo-form .form-element .form-field-container:hover{-webkit-box-shadow:none;box-shadow:none}.wpeo-form .form-element .form-field{-webkit-transition:all .2s ease-out;transition:all .2s ease-out;border-radius:0}.wpeo-form .form-element .form-field:hover{-webkit-box-shadow:none;box-shadow:none}.wpeo-form .form-element .form-sublabel{font-size:12px;font-style:italic;color:rgba(0,0,0,.6)}.wpeo-form .form-element .form-field-inline{margin-right:.4em}.wpeo-form .form-element.form-align-vertical .form-field-container{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.wpeo-form .form-element.form-align-horizontal .form-field-container{-ms-flex-wrap:wrap;flex-wrap:wrap}.wpeo-form .form-element .form-field-container .form-field,.wpeo-form .form-element .form-field-container [class*=form-field-icon]{background:#ececec}.wpeo-form .form-element .form-field-container:hover .form-field,.wpeo-form .form-element .form-field-container:hover [class*=form-field-icon]{background:#dfdfdf}.wpeo-form .form-element [class*=form-field-label]{background:#dfdfdf}.wpeo-form.form-light .form-element .form-field-container .form-field,.wpeo-form.form-light .form-element .form-field-container [class*=form-field-icon]{background:#fff}.wpeo-form.form-light .form-element .form-field-container:hover .form-field,.wpeo-form.form-light .form-element .form-field-container:hover [class*=form-field-icon]{background:#ececec}.wpeo-form.form-light .form-element [class*=form-field-label]{background:#ececec}.wpeo-form .form-element [class*=form-field-icon]{padding:.8em 0 .8em .8em;color:rgba(0,0,0,.4);font-size:16px;-webkit-transition:all .2s ease-out;transition:all .2s ease-out}.wpeo-form .form-element [class*=form-field-icon] [class*=fa]{vertical-align:middle}.wpeo-form .form-element .form-field-icon-prev{padding:.8em 0 .8em .8em}.wpeo-form .form-element .form-field-icon-next{padding:.8em .8em .8em 0}.wpeo-form .form-element [class*=form-field-label]{padding:1.2em 1em;font-size:12px}.wpeo-form .form-element .form-field-label-prev{border-right:1px solid rgba(0,0,0,.1)}.wpeo-form .form-element .form-field-label-next{border-left:1px solid rgba(0,0,0,.1)}.wpeo-form .form-element.form-element-required .form-label::after{display:inline-block;content:"*";color:#e05353;padding:0 .4em}.wpeo-form .form-element.form-element-error .form-field-container{border:1px solid #e05353}.wpeo-form .form-element.form-element-disable .form-field-container{opacity:.6;pointer-events:none}.digirisk-signature-container{max-width:800px;background:#fff;-webkit-box-shadow:0 0 40px 0 rgba(0,0,0,.1);box-shadow:0 0 40px 0 rgba(0,0,0,.1);margin:1.5em auto 0 auto;padding:2em;-webkit-box-sizing:border-box;box-sizing:border-box}.digirisk-signature-container *{-webkit-box-sizing:border-box;box-sizing:border-box}.digirisk-signature-container .signature .signature-element .wpeo-button.modal-signature-open{display:none}.digirisk-signature-container .signature .signature-element img{width:100%;height:auto;border:1px solid rgba(0,0,0,.4) !important}.table-cell-header{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;margin-bottom:.5em}.table-cell-header>*{margin:auto 0}.table-cell-header .wpeo-button{margin:0}.riskassessment-tasks .riskassessment-task-container,.riskassessment-task-container{min-width:430px;border:1px solid rgba(0,0,0,.1);background:rgba(0,0,0,.05);padding:.5em}.riskassessment-tasks{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.riskassessment-tasks .riskassessment-task-container{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.riskassessment-tasks .riskassessment-task-add-wrapper{min-width:calc(40px + .5em);margin:auto 0;text-align:center}.riskassessment-task-listing-wrapper .riskassessment-task-container{margin-bottom:.5em}.riskassessment-task-container .riskassessment-task-single{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-sizing:border-box;box-sizing:border-box}.riskassessment-task-container .riskassessment-task-single *{-webkit-box-sizing:border-box;box-sizing:border-box}.riskassessment-task-container .riskassessment-task-single>*{margin-top:auto;margin-bottom:auto}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content{width:100%}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-author{display:inline-block;width:25px;min-width:25px;height:25px;line-height:25px;background:rgba(0,0,0,.5);overflow:hidden;text-transform:uppercase;font-size:14px;font-weight:600;border-radius:50%;vertical-align:sub;text-align:center}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-author a{color:#fff !important}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-author-label{word-break:break-all}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;font-size:14px}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data>*{margin:auto .2em}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-reference{color:#263c5c;font-weight:600}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-reference:hover{text-decoration:underline;cursor:pointer}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-count{background:rgba(0,0,0,.2);font-size:12px;border-radius:4px;padding:.2em .4em}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress{background:rgba(0,0,0,.2);font-size:12px;border-radius:4px;padding:.2em .4em;font-weight:700;color:rgba(0,0,0,.6)}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-0{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-1{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-2{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-3{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-4{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-5{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-6{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-7{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-8{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-9{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-10{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-11{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-12{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-13{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-14{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-15{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-16{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-17{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-18{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-19{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-20{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-21{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-22{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-23{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-24{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-25{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-26{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-27{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-28{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-29{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-30{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-31{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-32{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-33{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-34{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-35{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-36{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-37{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-38{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-39{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-40{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-41{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-42{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-43{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-44{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-45{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-46{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-47{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-48{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-49{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-50{background:#e05353;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-51{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-52{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-53{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-54{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-55{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-56{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-57{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-58{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-59{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-60{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-61{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-62{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-63{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-64{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-65{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-66{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-67{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-68{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-69{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-70{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-71{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-72{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-73{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-74{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-75{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-76{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-77{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-78{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-79{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-80{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-81{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-82{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-83{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-84{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-85{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-86{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-87{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-88{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-89{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-90{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-91{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-92{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-93{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-94{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-95{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-96{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-97{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-98{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-99{background:#e9ad4f;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-content .riskassessment-task-data .riskassessment-task-progress.progress-100{background:#47e58e;color:#fff}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-title{display:-webkit-box;display:-ms-flexbox;display:flex}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-title .riskassessment-task-progress-checkbox{margin:auto 0}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-title .riskassessment-task-progress-checkbox input{width:20px;height:20px}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-add{min-width:40px;margin-left:.5em}.riskassessment-task-container .riskassessment-task-single .riskassessment-task-delete{margin-right:-0.5em}.riskassessment-task-listing-wrapper{width:100%}.riskassessment-task-add{margin:5px}.riskassessment-task-list{margin:5px}.riskassessment-task-timespent-add-container{display:-webkit-box;display:-ms-flexbox;display:flex;background:rgba(0,0,0,.1);padding:10px;margin-bottom:25px}.riskassessment-task-timespent-add-container>*{margin:auto 5px}.riskassessment-task-timespent-add-container .timespent-comment{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.riskassessment-task-timespent-add-container .timespent-date{min-width:250px}.riskassessment-task-timespent-add-container .timespent-duration{max-width:100px}.riskassessment-task-timespent-add-container .timespent-add-button{min-width:30px}.riskassessment-task-timespent-add-container .timespent-add-button .wpeo-button{margin-top:20px}.riskassessment-task-timespent-container .riskassessment-task .riskassessment-task-container{background:#fff;border:0}.wpeo-modal[class*=modal-riskassessment-task] .modal-container .title{display:block;font-weight:600;font-size:13px;margin-bottom:.6em;color:rgba(0,0,0,.8)}.wpeo-modal[class*=modal-riskassessment-task] .modal-container .title required{font-size:18px;color:#0d8aff;vertical-align:text-top;line-height:.9}.wpeo-modal[class*=modal-riskassessment-task] .modal-container .section-title{font-size:16px;color:rgba(0,0,0,.8);font-weight:600;margin-bottom:.6em;display:block}.wpeo-modal[class*=modal-riskassessment-task] .modal-container .riskassessment-task-single{display:block !important}.wpeo-modal[class*=modal-riskassessment-task] .modal-container .riskassessment-task-container{display:-webkit-box;display:-ms-flexbox;display:flex;padding-bottom:1em;margin-bottom:1em;border-bottom:1px solid rgba(0,0,0,.2)}.wpeo-modal[class*=modal-riskassessment-task] .modal-container .riskassessment-task-container .riskassessment-task{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.wpeo-modal[class*=modal-riskassessment-task] .modal-container .riskassessment-task-container .riskassessment-task input{width:100%}.wpeo-modal .modal-container .riskassessment-task-list .riskassessment-task>.riskassessment-task-container{display:-webkit-box;display:-ms-flexbox;display:flex}.wpeo-modal .modal-container .riskassessment-task-list .riskassessment-task>.riskassessment-task-container .riskassessment-task-single{width:100%}.wpeo-modal .modal-container .riskassessment-task-list .riskassessment-task>.riskassessment-task-container .riskassessment-task-actions{margin-left:auto}.wpeo-modal.modal-photo.modal-active{z-index:2014}.wpeo-modal.modal-photo .clickable-photo{border:5px solid #fff;-webkit-transition:all .2s ease-out;transition:all .2s ease-out;width:100%}.wpeo-modal.modal-photo .clickable-photo:hover{cursor:pointer}.wpeo-modal.modal-photo .clickable-photo:hover .photo-image .photo{opacity:.8}.wpeo-modal.modal-photo .clickable-photo .photo-image{position:relative;width:100%;max-width:120px;height:120px;margin:auto}.wpeo-modal.modal-photo .clickable-photo .photo-image .photo{position:absolute;top:0;left:0;width:100%;-o-object-fit:cover;object-fit:cover;max-width:none !important;-webkit-transition:all .2s ease-out;transition:all .2s ease-out}.wpeo-modal.modal-photo .clickable-photo .photo-image .clicked-photo-preview{position:absolute;display:inline-block;top:1em;right:1em;z-index:900;height:25px;line-height:25px;background:#fff;color:#0d8aff;-webkit-transition:all .2s ease-out;transition:all .2s ease-out}.wpeo-modal.modal-photo .clickable-photo .photo-image .clicked-photo-preview:hover{-webkit-transform:scale(1.1);transform:scale(1.1)}.wpeo-modal.modal-photo .clickable-photo .photo-image .clicked-photo-preview i{line-height:25px;font-size:14px}.wpeo-modal.modal-photo .clickable-photo .title{word-break:break-all}.wpeo-modal.modal-photo .formattachnewfile{padding-bottom:.5em}.wpeo-modal.modal-photo input[type=file]{border-bottom:0 !important}.wpeo-modal .modal-container ul,.wpeo-modal .modal-container li{margin:0;list-style-type:none;padding:0}@media(max-width: 1200px){td>.riskassessment-task-container{min-width:0}}.imgTabTitle{max-height:32px;vertical-align:middle} diff --git a/css/index.php b/css/index.php new file mode 100644 index 0000000..cd6990e --- /dev/null +++ b/css/index.php @@ -0,0 +1,2 @@ + .riskassessment-task-container { + display: flex; + + .riskassessment-task-single { + width: 100%; + } + .riskassessment-task-actions { + margin-left: auto; + } + } +} diff --git a/css/scss/modal/index.php b/css/scss/modal/index.php new file mode 100644 index 0000000..cd6990e --- /dev/null +++ b/css/scss/modal/index.php @@ -0,0 +1,2 @@ + classe de base pour un bouton + * .primary + * .light + * .dark + * .red + * .yellow + * .blue + * .green + * .transparent + * .bordered -> Change l'affichage du bouton. Fonctionne avec les même couleurs + * .strong -> texte en gras + * .uppercase -> texte en majuscule + * .float-right -> float right + * .float-left -> float left + * .square-30 -> bouton carré 30px + * .square-40 -> bouton carré 40px + * .square-50 -> bouton carré 50px + * .square-60 -> bouton carré 60px + * .margin -> margin haut et bas sur le bouton + * .radius-1 -> Arrondis les bords + * .radius-3 -> Arrondis les bords + * .radius-3 -> Arrondis les bords + * .rounded -> bouton en forme de rond + * .disable -> désactive les actions sur le bouton + * .size-small -> petite taille + * .size-large -> grande taille +--------------------------------------------------------------*/ + +.wpeo-button { + display: inline-block; + border: 0; + box-shadow: none; + background: none; + text-decoration: none; + padding: 6px 14px; + line-height: 1.4; + vertical-align: middle; + height: auto; + border-radius: 0; + transition: all 0.2s ease-out; + position: relative; + border-width: 3px; + border-style: solid; + font-size: 16px; + box-sizing: border-box; + + background: $color__primary; + border-color: $color__primary; + color: #fff; + + &:focus, &:visited { + color: #fff; + } + &:hover { + color: #fff; + box-shadow: inset 0 -2.6em rgba(255,255,255,0.25); + cursor: pointer; + text-decoration: none; + } + &:focus, &:active { + outline: none; + } +} + +/** Colors */ +@import "colors"; +@import "button-add"; + +// Icon +.wpeo-button { + .button-icon, span { + position: relative; + } + .button-icon ~ span { + margin-left: 10px; + } + span ~ .button-icon { + margin-left: 10px; + } +} + +// Strong +.wpeo-button.button-strong { + span { + font-weight: 800; + } +} + +// Uppercase +.wpeo-button.button-uppercase { + span { + text-transform: uppercase; + font-size: 14px; + } +} + +// Squared +.wpeo-button[class*="button-square-"] { + text-align: center; + overflow: hidden; + padding: 0; +} +.wpeo-button.button-square-30 { + width: 30px; + height: 30px; + line-height: 24px; // ne pas oublier les bordures : 6px + + .button-icon { + font-size: 12px; + line-height: 24px; + } +} +.wpeo-button.button-square-40 { + width: 40px; + height: 40px; + line-height: 34px; // ne pas oublier les bordures : 6px + + .button-icon { + line-height: 34px; + } +} +.wpeo-button.button-square-50 { + width: 50px; + height: 50px; + line-height: 44px; // ne pas oublier les bordures : 6px + + .button-icon { + line-height: 44px; + } +} +.wpeo-button.button-square-60 { + width: 60px; + height: 60px; + line-height: 54px; // ne pas oublier les bordures : 6px + + .button-icon { + line-height: 54px; + } +} + +// Floats +.wpeo-button { + &.button-float-left { + float: left; + } + &.button-float-right { + float: right; + } +} + +// margin +.wpeo-button.button-margin { + margin: 1em 0; +} + +// radius +.wpeo-button { + &.button-radius-1 { + border-radius: 2px; + } + &.button-radius-2 { + border-radius: 4px; + } + &.button-radius-3 { + border-radius: 6px; + } + &.button-rounded { + border-radius: 50%; + } +} + +// disable +.wpeo-button.button-disable { + background: $color__grey !important; + border-color: $color__grey !important; + color: rgba(0,0,0,0.4) !important; + pointer-events: none; + + &:hover { + box-shadow: none !important; + } + &.button-event { + pointer-events: all; + } +} + +// Taille +.wpeo-button.button-size-small { + font-size: 14px; + &.button-uppercase span { + font-size: 12px; + } +} +.wpeo-button.button-size-large { + font-size: 18px; + &.button-uppercase span { + font-size: 16px; + } +} diff --git a/css/scss/module/button/_colors.scss b/css/scss/module/button/_colors.scss new file mode 100644 index 0000000..7c0e446 --- /dev/null +++ b/css/scss/module/button/_colors.scss @@ -0,0 +1,138 @@ +// Bouton plein +.wpeo-button { + /* par défaut */ + background: $color__primary; + border-color: $color__primary; + color: $color__primary-text; + + &.button-main { + background: $color__primary; + border-color: $color__primary; + color: $color__primary-text; + } + &.button-secondary { + background: $color__secondary; + border-color: $color__secondary; + color: $color__secondary-text; + } + &.button-light { + background: #fff; + border-color: #fff; + color: $color__text-main; + &:hover { + box-shadow: inset 0 -2.6em rgba(0,0,0,0.1); + color: $color__text-main; + } + } + &.button-dark { + background: $color__dark; + border-color: $color__dark; + } + &.button-grey { + background: $color__grey; + border-color: $color__grey; + color: $color__text-main; + &:hover { + box-shadow: inset 0 -2.6em rgba(0,0,0,0.1); + color: $color__text-main; + } + } + &.button-red { + background: $color__red; + border-color: $color__red; + } + &.button-yellow { + background: $color__yellow; + border-color: $color__yellow; + } + &.button-blue { + background: $color__blue; + border-color: $color__blue; + } + &.button-green { + background: $color__green; + border-color: $color__green; + } + &.button-transparent { + background: transparent; + border-color: transparent; + color: rgba($color__text-main, 0.4); + &:hover { + color: $color__text-main; + box-shadow: inset 0 -2.6em rgba(255,255,255,0); + } + } +} + +// Bordered +.wpeo-button.button-bordered { + background: none; + /* Par defaut */ + border-color: $color__primary; + color: $color__primary; + + &.button-main { + border-color: $color__primary; + color: $color__primary; + &:hover { + box-shadow: inset 0 -2.6em $color__primary; + color: $color__primary-text; + } + } + &.button-light { + border-color: #fff; + color: #fff; + &:hover { + box-shadow: inset 0 -2.6em #fff; + color: $color__text-main; + } + } + &.button-dark { + border-color: $color__dark; + color: $color__dark; + &:hover { + box-shadow: inset 0 -2.6em $color__dark; + } + } + &.button-grey { + border-color: $color__grey; + color: darken($color__grey, 30%); + &:hover { + box-shadow: inset 0 -2.6em $color__grey; + color: $color__text-main; + } + } + &.button-red { + border-color: $color__red; + color: $color__red; + &:hover { + box-shadow: inset 0 -2.6em $color__red; + } + } + &.button-yellow { + border-color: $color__yellow; + color: $color__yellow; + &:hover { + box-shadow: inset 0 -2.6em $color__yellow; + } + } + &.button-blue { + border-color: $color__blue; + color: $color__blue; + &:hover { + box-shadow: inset 0 -2.6em $color__blue; + } + } + &.button-green { + border-color: $color__green; + color: $color__green; + &:hover { + box-shadow: inset 0 -2.6em $color__green; + } + } + + &:hover { + box-shadow: inset 0 -2.6em $color__primary; + color: #fff; + } +} diff --git a/css/scss/module/button/index.php b/css/scss/module/button/index.php new file mode 100644 index 0000000..cd6990e --- /dev/null +++ b/css/scss/module/button/index.php @@ -0,0 +1,2 @@ + classe de base du mobule + .grid -> Affichage en grille + .list -> Affichage en liste +--------------------------------------------------------------*/ + +.wpeo-dropdown { + position: relative; + display: inline-block; + + .dropdown-toggle { + display: inline-block; + + span ~ *[class*="icon"]{ + margin-left: 10px; + } + } + .dropdown-content { + opacity: 0; + pointer-events: none; + transform: translateY(-10px); + transition: all 0.2s ease-out; + position: absolute; + background: #fff; + z-index: 99; + border: 1px solid rgba(0,0,0,0.1); + box-shadow: 0 0 10px 0px rgba(0,0,0,0.3); + width: 220px; + padding: 0.6em; + } + &.dropdown-active .dropdown-content { + opacity: 1; + pointer-events: auto; + transform: translateY(0); + } + ul, li { + margin: 0; + list-style-type: none; + padding: 0; + } + .dropdown-item { + display: block; + color: rgba(0,0,0,0.7); + text-decoration: none; + + &::before { + display: none; + content: ''; + } + + .dropdown-result-title, .dropdown-result-subtitle { + display: block; + } + .dropdown-result-title { + font-size: 14px; + } + .dropdown-result-subtitle { + font-size: 12px; + color: rgba(0,0,0,0.5); + } + } +} + +/** Taille */ +.wpeo-dropdown { + &.dropdown-small .dropdown-content { + width: 60px; + } + &.dropdown-medium .dropdown-content { + width: 220px; + } + &.dropdown-large .dropdown-content { + width: 360px; + } +} + +/** Padding */ +.wpeo-dropdown { + &.dropdown-padding-0 .dropdown-content { + padding: 0; + } + &.dropdown-padding-1 .dropdown-content { + padding: 0.6em; + } + &.dropdown-padding-2 .dropdown-content { + padding: 1.2em; + } +} + +/** Alignement */ +.wpeo-dropdown { + &.dropdown-left .dropdown-content { + left: 0; + } + &.dropdown-right .dropdown-content { + right: 0; + } + + &.dropdown-horizontal.dropdown-left .dropdown-content { + left: 100%; + } + &.dropdown-horizontal.dropdown-right .dropdown-content { + right: 100%; + } +} + +/** Sens */ +.wpeo-dropdown { + &.dropdown-horizontal .dropdown-content { + top: 0; + width: auto !important; + display: flex; + flex-wrap: nowrap; + flex-direction: row; + } +} + +/** Disable */ +.wpeo-dropdown .dropdown-item { + &.dropdown-item-disable { + opacity: 0.6; + cursor: default !important; + pointer-events: none; + // Pointer events: none; seulement sur les enfants pour permettre l'utilisation d'une tooltip ou autre module. + > * { + } + } +} + +@import "list"; +@import "grid"; diff --git a/css/scss/module/dropdown/_grid.scss b/css/scss/module/dropdown/_grid.scss new file mode 100644 index 0000000..b601371 --- /dev/null +++ b/css/scss/module/dropdown/_grid.scss @@ -0,0 +1,11 @@ +.wpeo-dropdown.dropdown-grid { + .dropdown-item { + + img { + width: 100%; + height: auto; + display: block; + margin: 0; + } + } +} diff --git a/css/scss/module/dropdown/_list.scss b/css/scss/module/dropdown/_list.scss new file mode 100644 index 0000000..a2ca76a --- /dev/null +++ b/css/scss/module/dropdown/_list.scss @@ -0,0 +1,30 @@ +.wpeo-dropdown { + .dropdown-content { + .dropdown-item { + padding: 0.6em; + background: #fff; + transition: all 0.2s ease-out; + &:hover { + cursor: pointer; + background: rgba(0,0,0,0.1); + } + } + } +} + +.wpeo-dropdown.dropdown-list { + .dropdown-content { + text-align: left; + } + .dropdown-item { + &::after { + display: block; + content: ''; + clear: both; + } + img { + float: left; + margin-right: 0.4em; + } + } +} diff --git a/css/scss/module/dropdown/index.php b/css/scss/module/dropdown/index.php new file mode 100644 index 0000000..cd6990e --- /dev/null +++ b/css/scss/module/dropdown/index.php @@ -0,0 +1,2 @@ + .svg-inline--fa { + position: absolute; + right: 1em; + top: 50%; + transform: translateY(-50%); + } +} +.wpeo-form .form-element.disable { + .dropdown-toggle > .svg-inline--fa { + display: none; + } +} + +/* Compatibility Autocomplete */ +.wpeo-form .wpeo-autocomplete { + display: block; + width: 100%; + .autocomplete-label { + box-shadow: none; + padding: 0.74em 1em; + } +} +.wpeo-form.form-light { + .wpeo-autocomplete .autocomplete-label { + background: #fff; + &:hover { + background: $color__grey; + } + } +} diff --git a/css/scss/module/form/_radio.scss b/css/scss/module/form/_radio.scss new file mode 100644 index 0000000..7849110 --- /dev/null +++ b/css/scss/module/form/_radio.scss @@ -0,0 +1,53 @@ +/** Général */ +.wpeo-form .form-element { + input[type="radio"].form-field { + display: inline-block; + width: auto; + } +} + +/** Design */ +.wpeo-form .form-element { + input[type="radio"].form-field { + appearance: none; + border-radius: 50%; + width: 16px; + height: 16px; + padding: 0; + border: 0; + background: transparent !important; + border: 1px solid rgba(0,0,0,0.4); + transition: 0.2s all linear; + outline: none; + position: relative; + top: 2px; + + &::before { + display: none !important; + content: '' !important; + } + &:hover { + cursor: pointer; + border: 1px solid $color__primary; + box-shadow: 0 0 0 1px $color__primary inset; + background: transparent !important; + } + &:checked { + border: 1px solid $color__primary; + box-shadow: 0 0 0 4px $color__primary inset; + } + & + label { + text-transform: none; + font-weight: 400; + font-size: 14px; + display: inline-block; + margin-right: 1em; + &:hover { + cursor: pointer; + } + &:active { + outline: none; + } + } + } +} diff --git a/css/scss/module/gridlayout/_gridlayout.scss b/css/scss/module/gridlayout/_gridlayout.scss new file mode 100644 index 0000000..e73cb7c --- /dev/null +++ b/css/scss/module/gridlayout/_gridlayout.scss @@ -0,0 +1,120 @@ +/*-------------------------------------------------------------- + Module : Gridlayout + Version : 1.5.0 + + * Classes pour l'élément parent + .wpeo-gridlayout -> classe de base du mobule + .grid-X -> Définit le nombre de colonnes + .grid-margin-X -> Ajoute des marges au dessus et en dessous du parent + .grid-gap-X -> Définit les gouttières des colonnes + + * Classes pour les enfants direct + .gridw-X -> Change la largeur du bloc enfant (gridw-2 = 2 fois la taille initiale) + .gridh-X -> Change la hauteur du bloc enfant (gridh-2 = 2 fois la taille initiale) +--------------------------------------------------------------*/ + +.wpeo-gridlayout { + display: grid; + grid-gap: 1em 1em; + grid-template-columns: repeat( 4, 1fr ); +} + +/** Définition des tailles */ +.wpeo-gridlayout { + /** Du parent */ + @for $i from 1 through 6 { + &.grid-#{$i} { + grid-template-columns: repeat( $i, 1fr ); + } + + /** Chaque enfant peut modifier sa propre taille */ + @for $y from 1 through 6 { + @if ( $y <= $i ) { + &.grid-#{$i} > .gridw-#{$y} { + grid-column: auto / span $y; + + @if ( $y > 1 ) { + @media ( max-width: $media__medium ) { + grid-column: auto / span 2; + } + } + } + } + } + } +} + +/** Définition des hauteur des enfants */ +.wpeo-gridlayout { + @for $i from 1 through 6 { + > .gridh-#{$i} { + grid-row: auto / span $i; + + @media ( max-width: $media__medium ) { + grid-row: auto / span 1 !important; + } + } + } +} + +/** Marges */ +.wpeo-gridlayout { + @for $i from 0 through 6 { + &.grid-margin-#{$i} { + margin: #{$i}em 0; + } + } +} + +/** Gouttières */ +.wpeo-gridlayout { + @for $i from 0 through 6 { + &.grid-gap-#{$i} { + grid-gap: #{$i}em #{$i}em; + } + } +} + +/** Alignements */ +.wpeo-gridlayout { + .grid-align-center { + margin-left: auto; + margin-right: auto; + } + .grid-align-right { + margin-left: auto; + } + .grid-align-middle { + margin-top: auto; + margin-bottom: auto; + } + .grid-align-bottom { + margin-top: auto; + } +} + +/** Media queries */ +.wpeo-gridlayout:not(.dropdown-content) { + @for $i from 1 through 6 { + @if ( $i > 2 ) { + @media ( max-width: $media__medium ) { + &.grid-#{$i} { + grid-template-columns: repeat( 2, 1fr ) !important; + } + } + } + @if ( $i > 1 ) { + @media ( max-width: $media__small ) { + &.grid-#{$i} { + grid-template-columns: repeat( 1, 1fr ) !important; + } + } + } + + } + > * { + @media ( max-width: $media__small ) { + grid-column: auto / span 1 !important; + } + } +} diff --git a/css/scss/module/gridlayout/index.php b/css/scss/module/gridlayout/index.php new file mode 100644 index 0000000..cd6990e --- /dev/null +++ b/css/scss/module/gridlayout/index.php @@ -0,0 +1,2 @@ + classe de base pour le module + .loader-spin => icone de chargement +--------------------------------------------------------------*/ + +.wpeo-loader { + transition: all 0.2s ease-out; + pointer-events: none; + opacity: 0.5; + position: relative; + + .loader-spin { + position: absolute; + border: 3px solid #a7a7a7; + border-top: 3px solid darken($color__primary, 40%); + border-radius: 50%; + width: 20px; + height: 20px; + z-index: 99; + left: 50%; + top: 50%; + margin: 0 !important; + padding: 0 !important; + animation: loader-spin 1s ease-out infinite; + } +} + + + @keyframes loader-spin { + 0% { transform: translate(-50%, -50%) rotate(0deg); } + 100% { transform: translate(-50%, -50%) rotate(360deg); } + } diff --git a/css/scss/module/loader/index.php b/css/scss/module/loader/index.php new file mode 100644 index 0000000..cd6990e --- /dev/null +++ b/css/scss/module/loader/index.php @@ -0,0 +1,2 @@ + classe de base du mobule + .modalactive -> lance l'apparition de la modal + .no-modal-close -> désactive l'icone fermeture +--------------------------------------------------------------*/ + +.wpeo-modal { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1000; + background: rgba(39,42,53,.9); + opacity: 0; + pointer-events: none; + transition: all 0.2s ease-out; + + // Fix pointer event on textarea field. + textarea { + resize: none; + } + + &.modal-active { + opacity: 1; + pointer-events: auto; + z-index: 1002; + + .modal-container { + transform: translate(-50%, -50%); + } + textarea { + resize: both; + } + } + + // Fix 2eme niveau modal. + &.modal-active .modal-active { + z-index: 1003; + } + // Fix 3eme niveau modal. + &.modal-active .modal-active .modal-active { + z-index: 1004; + } + + &.modal-force-display { + .modal-close { + display: none; + } + } +} + +.wpeo-modal { + .modal-container { + position: absolute; + transition: all 0.2s ease-out; + width: 100%; + max-width: 860px; + height: 100%; + max-height: 560px; + background: #fff; + padding: 1em 0; + margin: auto; + top: 50%; + left: 50%; + transform: translate(-50%, -60%); + @media ( max-width: $media__small ) { + padding: 1em; + } + } + + .modal-container { + .modal-header { + height: 10%; + display: flex; + padding: 0 2em; + } + .modal-content { + height: 78%; + padding: 0 2em; + } + .modal-footer { + height: 12%; + padding: 0 2em; + } + } + .modal-container .modal-header { + .modal-title, .modal-close { + margin: auto 0; + } + .modal-title { + text-transform: uppercase; + font-size: 18px; + white-space: normal; + @media ( max-width: $media__medium ) { + font-size: 16px; + } + @media ( max-width: $media__small ) { + font-size: 14px; + } + } + .modal-close { + margin-left: auto; + color: rgba(0,0,0,0.3); + padding: 4px; + transition: all 0.2s ease-out; + &:hover { + cursor: pointer; + color: $color__primary; + } + } + } + .modal-container .modal-content { + overflow-y: auto; + font-size: 14px; + @media ( max-width: $media__small ) { + font-size: 12px; + } + } + .modal-container .modal-footer { + text-align: right; + padding-top: 1em; + &.left { + text-align: left; + } + &.center { + text-align: center; + } + } +} diff --git a/css/scss/module/modal/index.php b/css/scss/module/modal/index.php new file mode 100644 index 0000000..cd6990e --- /dev/null +++ b/css/scss/module/modal/index.php @@ -0,0 +1,2 @@ + classe de base du mobule +--------------------------------------------------------------*/ + +/* General */ +.wpeo-notice { + position: relative; + font-size: 1em; + padding: 1em; + overflow: hidden; + border-radius: 3px; + border: solid #eee 1px; + margin: 1em 0; + display: flex; + transition: all 0.2s ease-out; + align-items: center; + + &::before { + display: block; + font-family: 'Font Awesome 5 Free'; + font-weight: 900; + font-size: 24px; + } + .notice-content { + width: 100%; + padding: 0 1em; + color: rgba(0,0,0,0.6); + } + .notice-title { + font-size: 20px; + font-weight: 600; + color: rgba(0,0,0,0.9); + } + .notice-subtitle { + font-size: 14px; + } + .notice-close { + color: rgba(0,0,0,0.3); + transition: all 0.2s ease-out; + + &:hover { + color: $color__primary; + cursor: pointer; + } + } + ul { + padding: 0 0 0 1.4em; + margin: 0.4em 0; + } +} + +/** Status */ +@import "status"; diff --git a/css/scss/module/notice/_status.scss b/css/scss/module/notice/_status.scss new file mode 100644 index 0000000..ba3f02e --- /dev/null +++ b/css/scss/module/notice/_status.scss @@ -0,0 +1,55 @@ +/** Info */ +.wpeo-notice.notice-info { + border-left: solid $color__blue 6px; + color: $color__blue; + background: rgba( $color__blue, 0.05 ); + + &::before { + content: '\f05a'; + } + .notice-title, .notice-subtitle, a { + color: $color__blue; + } +} + +/** Error */ +.wpeo-notice.notice-error { + border-left: solid $color__red 6px; + color: $color__red; + background: rgba( $color__red, 0.05 ); + + &::before { + content: '\f057'; + } + .notice-title, .notice-subtitle, a { + color: $color__red; + } +} + +/** Warning */ +.wpeo-notice.notice-warning { + border-left: solid $color__yellow 6px; + color: $color__yellow; + background: rgba( $color__yellow, 0.05 ); + + &::before { + content: '\f071'; + } + .notice-title, .notice-subtitle, a { + color: $color__yellow; + } +} + +/** Success */ +.wpeo-notice.notice-success { + border-left: solid $color__green 6px; + color: $color__green; + background: rgba( $color__green, 0.05 ); + + &::before { + content: '\f058'; + } + .notice-title, .notice-subtitle, a { + color: $color__green; + } +} diff --git a/css/scss/module/notice/index.php b/css/scss/module/notice/index.php new file mode 100644 index 0000000..cd6990e --- /dev/null +++ b/css/scss/module/notice/index.php @@ -0,0 +1,2 @@ + classe de base du mobule +--------------------------------------------------------------*/ + + +@import "flex"; diff --git a/css/scss/module/table/index.php b/css/scss/module/table/index.php new file mode 100644 index 0000000..cd6990e --- /dev/null +++ b/css/scss/module/table/index.php @@ -0,0 +1,2 @@ + classe de base du mobule + .tooltip-primary -> tooltip sur fond rouge + .tooltip-light -> tooltip sur fond rouge + .tooltip-red -> tooltip sur fond rouge +--------------------------------------------------------------*/ + +.wpeo-tooltip { + display: block; + position: absolute; + bottom: 0; + left: 0; + opacity: 0; + pointer-events: none; + z-index: 99999; + white-space: nowrap; + background: $color__dark; + color: #fff; + border-radius: 6px; + font-size: 0.8rem; + padding: 0 1em; + height: 2.2em; + line-height: 2.2em; + + &::before { + display: block; + content: ''; + width: 0; + height: 0; + border-style: solid; + position: absolute; + } + &:focus { + outline: none; + } +} + +/* Couleurs */ +@mixin set-arrow-color($color) { + &.tooltip-top::before { + border-color: $color transparent transparent transparent; + } + &.tooltip-right::before { + border-color: transparent $color transparent transparent; + } + &.tooltip-bottom::before { + border-color: transparent transparent $color transparent; + } + &.tooltip-left::before { + border-color: transparent transparent transparent $color; + } +} + +.wpeo-tooltip { + &.tooltip-dark { + background: $color__dark; + @include set-arrow-color($color__dark); + } + &.tooltip-primary { + background: $color__primary; + @include set-arrow-color($color__primary); + } + &.tooltip-light { + background: $color__grey; + color: rgba(0,0,0,0.6); + @include set-arrow-color($color__grey); + } + &.tooltip-red { + background: $color__red; + @include set-arrow-color($color__red); + } +} + +/* Position de la fleche */ +.wpeo-tooltip { + &.tooltip-top::before { + border-width: 6px 6px 0 6px; + border-color: $color__dark transparent transparent transparent; + bottom: -6px; + left: 50%; + transform: translateX(-50%); + } + &.tooltip-right::before { + border-width: 6px 6px 6px 0; + border-color: transparent $color__dark transparent transparent; + top: 50%; + transform: translateY(-50%); + left: -6px; + } + &.tooltip-bottom::before { + border-width: 0 6px 6px 6px; + border-color: transparent transparent $color__dark transparent; + top: -6px; + left: 50%; + transform: translateX(-50%); + } + &.tooltip-left::before { + border-width: 6px 0 6px 6px; + border-color: transparent transparent transparent $color__dark; + top: 50%; + transform: translateY(-50%); + right: -6px; + } +} diff --git a/css/scss/module/tooltip/index.php b/css/scss/module/tooltip/index.php new file mode 100644 index 0000000..cd6990e --- /dev/null +++ b/css/scss/module/tooltip/index.php @@ -0,0 +1,2 @@ + .riskassessment-task-container { + min-width: 0; + } +} diff --git a/css/scss/responsive/index.php b/css/scss/responsive/index.php new file mode 100644 index 0000000..cd6990e --- /dev/null +++ b/css/scss/responsive/index.php @@ -0,0 +1,2 @@ + * { + margin: auto 0; + } + .wpeo-button { + margin: 0; + } +} diff --git a/css/scss/table/_riskassessment-task.scss b/css/scss/table/_riskassessment-task.scss new file mode 100644 index 0000000..df2b629 --- /dev/null +++ b/css/scss/table/_riskassessment-task.scss @@ -0,0 +1,185 @@ +.riskassessment-tasks .riskassessment-task-container, .riskassessment-task-container { + min-width: 430px; + border: 1px solid rgba(0,0,0,0.1); + background: rgba(0,0,0,0.05); + padding: 0.5em; +} + +.riskassessment-tasks { + display: flex; + flex-wrap: nowrap; + align-items: center; + + .riskassessment-task-container { + flex-grow: 1; + } + .riskassessment-task-add-wrapper { + min-width: calc(40px + 0.5em); + margin: auto 0; + text-align: center; + } +} +.riskassessment-task-listing-wrapper .riskassessment-task-container { + margin-bottom: 0.5em; +} + +.riskassessment-task-container .riskassessment-task-single { + display: flex; + box-sizing: border-box; + + * { + box-sizing: border-box; + } + > * { + margin-top: auto; + margin-bottom: auto; + } + + .riskassessment-task-content { + width: 100%; + + .riskassessment-task-author { + display: inline-block; + width: 25px; + min-width: 25px; + height: 25px; + line-height: 25px; + background: rgba(0,0,0,0.5); + overflow: hidden; + text-transform: uppercase; + font-size: 14px; + font-weight: 600; + border-radius: 50%; + vertical-align: sub; + text-align: center; + + a { + color: #fff !important; + } + } + .riskassessment-task-author-label { + word-break: break-all; + } + } + .riskassessment-task-content .riskassessment-task-data { + display: flex; + flex-wrap: wrap; + font-size: 14px; + + > * { + margin: auto 0.2em; + } + + .riskassessment-task-reference { + color: $color__secondary; + font-weight: 600; + + &:hover { + text-decoration: underline; + cursor: pointer; + } + } + .riskassessment-task-count { + background: rgba(0,0,0,0.2); + font-size: 12px; + border-radius: 4px; + padding: 0.2em 0.4em; + } + .riskassessment-task-progress { + background: rgba(0, 0, 0, 0.2); + font-size: 12px; + border-radius: 4px; + padding: 0.2em 0.4em; + font-weight: 700; + color: rgba(0,0,0,0.6); + + @for $i from 0 through 50 { + &.progress-#{$i} { + background: $color__red; + color: #fff; + } + } + @for $i from 51 through 99 { + &.progress-#{$i} { + background: $color__yellow; + color: #fff; + } + } + &.progress-100 { + background: $color__green; + color: #fff; + } + } + } + + .riskassessment-task-title { + display: flex; + + .riskassessment-task-progress-checkbox { + margin: auto 0; + + input { + width: 20px; + height: 20px; + } + } + .riskassessment-task-author-label { + } + } + + .riskassessment-task-add { + min-width: 40px; + margin-left: 0.5em; + } + .riskassessment-task-delete { + margin-right: -0.5em; + } +} + +.riskassessment-task-listing-wrapper { + width: 100%; +} + +.riskassessment-task-add { + margin: 5px; +} + +.riskassessment-task-list { + margin: 5px; +} + + +/** Add comment in modal */ +.riskassessment-task-timespent-add-container { + display: flex; + background: rgba(0,0,0,0.1); + padding: 10px; + margin-bottom: 25px; + + > * { + margin: auto 5px; + } + .timespent-comment { + flex-grow: 1; + } + .timespent-date { + min-width: 250px; + } + .timespent-duration { + max-width: 100px; + } + .timespent-add-button { + min-width: 30px; + + .wpeo-button { + margin-top: 20px; + } + } +} + +/** List of comments */ +.riskassessment-task-timespent-container .riskassessment-task .riskassessment-task-container { + background: #fff; + border: 0; + +} diff --git a/css/scss/table/_table.scss b/css/scss/table/_table.scss new file mode 100644 index 0000000..dcfa210 --- /dev/null +++ b/css/scss/table/_table.scss @@ -0,0 +1,2 @@ +@import "general"; +@import "riskassessment-task"; diff --git a/css/scss/table/index.php b/css/scss/table/index.php new file mode 100644 index 0000000..cd6990e --- /dev/null +++ b/css/scss/table/index.php @@ -0,0 +1,2 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file dolisirhindex.php + * \ingroup dolisirh + * \brief Home page of dolisirh top menu + */ + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) $res = @include "../main.inc.php"; +if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; +if (!$res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; +if (!$res) die("Include of main fails"); + +// Libraries +require_once './core/modules/modDolisirh.class.php'; + +// Global variables definitions +global $conf, $db, $langs, $user; + +// Load translation files required by the page +$langs->loadLangs(array("dolisirh@dolisirh")); + +// Parameters +$action = GETPOST('action', 'alpha'); + +// Initialize technical objects +$dolisirh = new modDolisirh($db); + +// Security check +if (! $user->rights->dolisirh->lire) accessforbidden(); + +/* + * Actions +*/ + +require_once './core/tpl/dolisirh_projectcreation_action.tpl.php'; + +/* + * View + */ + +$help_url = 'FR:Module_DoliSIRH'; +$title = $langs->trans("DoliSIRHArea"); +$morejs = array("/dolisirh/js/dolisirh.js.php"); +$morecss = array("/dolisirh/css/dolisirh.css"); + +llxHeader('', $title . ' ' . $dolisirh->version, $help_url, '', 0, 0, $morejs, $morecss); + +print load_fiche_titre($title . ' ' . $dolisirh->version, '', 'dolisirh.png@dolisirh'); + +// End of page +llxFooter(); +$db->close(); diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..242ce39 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,30 @@ +'use strict'; + +var gulp = require('gulp'); +var sass = require('gulp-sass')(require('sass')); +var rename = require('gulp-rename'); +var autoprefixer = require('gulp-autoprefixer'); + +var paths = { + scss_core : [ 'css/scss/**/*.scss', 'css/' ] +}; + +/** Core */ +gulp.task( 'scss_core', function () { + return gulp.src(paths.scss_core[0]) + .pipe(sass({ 'outputStyle': 'expanded' }).on('error', sass.logError)) + .pipe( autoprefixer({ + browsers: ['last 2 versions'], + cascade: false + }) ) + .pipe(rename('./dolisirh.css')) + .pipe(gulp.dest(paths.scss_core[1])) + .pipe(sass({outputStyle: 'compressed'}).on('error', sass.logError)) + .pipe(rename('./dolisirh.min.css')) + .pipe(gulp.dest(paths.scss_core[1])); +}); + +/** Watch */ +gulp.task( 'default', function () { + gulp.watch(paths.scss_core[0], gulp.series('scss_core')); +}); diff --git a/img/dolisirh.png b/img/dolisirh.png new file mode 100644 index 0000000..2c282f6 Binary files /dev/null and b/img/dolisirh.png differ diff --git a/img/dolisirh32px.png b/img/dolisirh32px.png new file mode 100644 index 0000000..8c3cbaa Binary files /dev/null and b/img/dolisirh32px.png differ diff --git a/img/index.php b/img/index.php new file mode 100644 index 0000000..17927e6 --- /dev/null +++ b/img/index.php @@ -0,0 +1,2 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Library javascript to enable Browser notifications + */ + +if ( ! defined('NOREQUIRESOC')) { + define('NOREQUIRESOC', '1'); +} +if ( ! defined('NOCSRFCHECK')) { + define('NOCSRFCHECK', 1); +} +if ( ! defined('NOTOKENRENEWAL')) { + define('NOTOKENRENEWAL', 1); +} +if ( ! defined('NOLOGIN')) { + define('NOLOGIN', 1); +} +if ( ! defined('NOREQUIREMENU')) { + define('NOREQUIREMENU', 1); +} +if ( ! defined('NOREQUIREHTML')) { + define('NOREQUIREHTML', 1); +} +if ( ! defined('NOREQUIREAJAX')) { + define('NOREQUIREAJAX', '1'); +} + +session_cache_limiter('public'); + +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if ( ! $res && ! empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"] . "/main.inc.php"; +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } +if ( ! $res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1)) . "/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1)) . "/main.inc.php"; +if ( ! $res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1)) . "/../main.inc.php")) $res = @include substr($tmp, 0, ($i + 1)) . "/../main.inc.php"; +// Try main.inc.php using relative path +if ( ! $res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; +if ( ! $res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; +if ( ! $res) die("Include of main fails"); + +// Define javascript type +top_httphead('text/javascript; charset=UTF-8'); +// Important: Following code is to avoid page request by browser and PHP CPU at each Dolibarr page access. +if (empty($dolibarr_nocache)) { + header('Cache-Control: max-age=10800, public, must-revalidate'); +} else { + header('Cache-Control: no-cache'); +} +?> + +/** + * \file js/dolisirh.js.php + * \ingroup dolisirh + * \brief JavaScript file for module DoliSIRH. + */ + +/* Javascript library of module DoliSIRH */ + +'use strict'; +/** + * @namespace EO_Framework_Init + * + * @author Eoxia + * @copyright 2015-20222 Eoxia + */ + +if ( ! window.eoxiaJS ) { + /** + * [eoxiaJS description] + * + * @memberof EO_Framework_Init + * + * @type {Object} + */ + window.eoxiaJS = {}; + + /** + * [scriptsLoaded description] + * + * @memberof EO_Framework_Init + * + * @type {Boolean} + */ + window.eoxiaJS.scriptsLoaded = false; +} + +if ( ! window.eoxiaJS.scriptsLoaded ) { + /** + * [description] + * + * @memberof EO_Framework_Init + * + * @returns {void} [description] + */ + window.eoxiaJS.init = function() { + window.eoxiaJS.load_list_script(); + }; + + /** + * [description] + * + * @memberof EO_Framework_Init + * + * @returns {void} [description] + */ + window.eoxiaJS.load_list_script = function() { + if ( ! window.eoxiaJS.scriptsLoaded) { + var key = undefined, slug = undefined; + for ( key in window.eoxiaJS ) { + + if ( window.eoxiaJS[key].init ) { + window.eoxiaJS[key].init(); + } + + for ( slug in window.eoxiaJS[key] ) { + + if ( window.eoxiaJS[key] && window.eoxiaJS[key][slug] && window.eoxiaJS[key][slug].init ) { + window.eoxiaJS[key][slug].init(); + } + + } + } + + window.eoxiaJS.scriptsLoaded = true; + } + }; + + /** + * [description] + * + * @memberof EO_Framework_Init + * + * @returns {void} [description] + */ + window.eoxiaJS.refresh = function() { + var key = undefined; + var slug = undefined; + for ( key in window.eoxiaJS ) { + if ( window.eoxiaJS[key].refresh ) { + window.eoxiaJS[key].refresh(); + } + + for ( slug in window.eoxiaJS[key] ) { + + if ( window.eoxiaJS[key] && window.eoxiaJS[key][slug] && window.eoxiaJS[key][slug].refresh ) { + window.eoxiaJS[key][slug].refresh(); + } + } + } + }; + + $( document ).ready( window.eoxiaJS.init ); +} + +/** + * Initialise l'objet "modal" ainsi que la méthode "init" obligatoire pour la bibliothèque EoxiaJS. + * + * @since 1.4.0 + * @version 1.4.0 + */ +window.eoxiaJS.modal = {}; + +/** + * La méthode appelée automatiquement par la bibliothèque EoxiaJS. + * + * @since 1.4.0 + * @version 1.4.0 + * + * @return {void} + */ +window.eoxiaJS.modal.init = function() { + window.eoxiaJS.modal.event(); +}; + +/** + * La méthode contenant tous les événements pour la modal. + * + * @since 1.4.0 + * @version 1.4.0 + * + * @return {void} + */ +window.eoxiaJS.modal.event = function() { + $( document ).on( 'click', '.modal-close', window.eoxiaJS.modal.closeModal ); + $( document ).on( 'click', '.modal-open', window.eoxiaJS.modal.openModal ); + $( document ).on( 'click', '.modal-refresh', window.eoxiaJS.modal.refreshModal ); +}; + +/** + * Open Modal. + * + * @since 1.4.0 + * @version 1.4.0 + * + * @param {MouseEvent} event Les attributs lors du clic. + * @return {void} + */ +window.eoxiaJS.modal.openModal = function ( event ) { + let idSelected = $(this).attr('value'); + if (document.URL.match(/#/)) { + var urlWithoutTag = document.URL.split(/#/)[0] + } else { + var urlWithoutTag = document.URL + } + history.pushState({ path: document.URL}, '', urlWithoutTag); + + // Open modal signature. + if ($(this).hasClass('modal-signature-open')) { + $('#modal-signature' + idSelected).addClass('modal-active'); + window.eoxiaJS.signature.modalSignatureOpened( $(this) ); + } + + $('.notice').addClass('hidden'); +}; + +/** + * Close Modal. + * + * @since 1.4.0 + * @version 1.4.0 + * + * @param {MouseEvent} event Les attributs lors du clic. + * @return {void} + */ +window.eoxiaJS.modal.closeModal = function ( event ) { + $(this).closest('.modal-active').removeClass('modal-active') + $('.clicked-photo').attr('style', ''); + $('.clicked-photo').removeClass('clicked-photo'); + $('.notice').addClass('hidden'); +}; + +/** + * Refresh Modal. + * + * @since 1.4.0 + * @version 1.4.0 + * + * @param {MouseEvent} event Les attributs lors du clic. + * @return {void} + */ +window.eoxiaJS.modal.refreshModal = function ( event ) { + window.location.reload(); +}; + +/** + * [dropdown description] + * + * @memberof EO_Framework_Dropdown + * + * @type {Object} + */ +window.eoxiaJS.dropdown = {}; + +/** + * [description] + * + * @memberof EO_Framework_Dropdown + * + * @returns {void} [description] + */ +window.eoxiaJS.dropdown.init = function() { + window.eoxiaJS.dropdown.event(); +}; + +/** + * [description] + * + * @memberof EO_Framework_Dropdown + * + * @returns {void} [description] + */ +window.eoxiaJS.dropdown.event = function() { + $( document ).on( 'keyup', window.eoxiaJS.dropdown.keyup ); + $( document ).on( 'click', '.wpeo-dropdown:not(.dropdown-active) .dropdown-toggle:not(.disabled)', window.eoxiaJS.dropdown.open ); + $( document ).on( 'click', '.wpeo-dropdown.dropdown-active .dropdown-content', function(e) { e.stopPropagation() } ); + $( document ).on( 'click', '.wpeo-dropdown.dropdown-active:not(.dropdown-force-display) .dropdown-content .dropdown-item', window.eoxiaJS.dropdown.close ); + $( document ).on( 'click', '.wpeo-dropdown.dropdown-active', function ( e ) { window.eoxiaJS.dropdown.close( e ); e.stopPropagation(); } ); + $( document ).on( 'click', 'body', window.eoxiaJS.dropdown.close ); +}; + +/** + * [description] + * + * @memberof EO_Framework_Dropdown + * + * @param {void} event [description] + * @returns {void} [description] + */ +window.eoxiaJS.dropdown.keyup = function( event ) { + if ( 27 === event.keyCode ) { + window.eoxiaJS.dropdown.close(); + } +} + +/** + * [description] + * + * @memberof EO_Framework_Dropdown + * + * @param {void} event [description] + * @returns {void} [description] + */ +window.eoxiaJS.dropdown.open = function( event ) { + var triggeredElement = $( this ); + var angleElement = triggeredElement.find('[data-fa-i2svg]'); + var callbackData = {}; + var key = undefined; + + window.eoxiaJS.dropdown.close( event, $( this ) ); + + if ( triggeredElement.attr( 'data-action' ) ) { + window.eoxiaJS.loader.display( triggeredElement ); + + triggeredElement.get_data( function( data ) { + for ( key in callbackData ) { + if ( ! data[key] ) { + data[key] = callbackData[key]; + } + } + + window.eoxiaJS.request.send( triggeredElement, data, function( element, response ) { + triggeredElement.closest( '.wpeo-dropdown' ).find( '.dropdown-content' ).html( response.data.view ); + + triggeredElement.closest( '.wpeo-dropdown' ).addClass( 'dropdown-active' ); + + /* Toggle Button Icon */ + if ( angleElement ) { + window.eoxiaJS.dropdown.toggleAngleClass( angleElement ); + } + } ); + } ); + } else { + triggeredElement.closest( '.wpeo-dropdown' ).addClass( 'dropdown-active' ); + + /* Toggle Button Icon */ + if ( angleElement ) { + window.eoxiaJS.dropdown.toggleAngleClass( angleElement ); + } + } + + event.stopPropagation(); +}; + +/** + * [description] + * + * @memberof EO_Framework_Dropdown + * + * @param {void} event [description] + * @returns {void} [description] + */ +window.eoxiaJS.dropdown.close = function( event ) { + var _element = $( this ); + $( '.wpeo-dropdown.dropdown-active:not(.no-close)' ).each( function() { + var toggle = $( this ); + var triggerObj = { + close: true + }; + + _element.trigger( 'dropdown-before-close', [ toggle, _element, triggerObj ] ); + + if ( triggerObj.close ) { + toggle.removeClass( 'dropdown-active' ); + + /* Toggle Button Icon */ + var angleElement = $( this ).find('.dropdown-toggle').find('[data-fa-i2svg]'); + if ( angleElement ) { + window.eoxiaJS.dropdown.toggleAngleClass( angleElement ); + } + } else { + return; + } + }); +}; + +/** + * [description] + * + * @memberof EO_Framework_Dropdown + * + * @param {jQuery} button [description] + * @returns {void} [description] + */ +window.eoxiaJS.dropdown.toggleAngleClass = function( button ) { + if ( button.hasClass('fa-caret-down') || button.hasClass('fa-caret-up') ) { + button.toggleClass('fa-caret-down').toggleClass('fa-caret-up'); + } + else if ( button.hasClass('fa-caret-circle-down') || button.hasClass('fa-caret-circle-up') ) { + button.toggleClass('fa-caret-circle-down').toggleClass('fa-caret-circle-up'); + } + else if ( button.hasClass('fa-angle-down') || button.hasClass('fa-angle-up') ) { + button.toggleClass('fa-angle-down').toggleClass('fa-angle-up'); + } + else if ( button.hasClass('fa-chevron-circle-down') || button.hasClass('fa-chevron-circle-up') ) { + button.toggleClass('fa-chevron-circle-down').toggleClass('fa-chevron-circle-up'); + } +}; + +/** + * @namespace EO_Framework_Tooltip + * + * @author Eoxia + * @copyright 2015-2018 Eoxia + */ + +if ( ! window.eoxiaJS.tooltip ) { + + /** + * [tooltip description] + * + * @memberof EO_Framework_Tooltip + * + * @type {Object} + */ + window.eoxiaJS.tooltip = {}; + + /** + * [description] + * + * @memberof EO_Framework_Tooltip + * + * @returns {void} [description] + */ + window.eoxiaJS.tooltip.init = function() { + window.eoxiaJS.tooltip.event(); + }; + + window.eoxiaJS.tooltip.tabChanged = function() { + $( '.wpeo-tooltip' ).remove(); + } + + /** + * [description] + * + * @memberof EO_Framework_Tooltip + * + * @returns {void} [description] + */ + window.eoxiaJS.tooltip.event = function() { + $( document ).on( 'mouseenter touchstart', '.wpeo-tooltip-event:not([data-tooltip-persist="true"])', window.eoxiaJS.tooltip.onEnter ); + $( document ).on( 'mouseleave touchend', '.wpeo-tooltip-event:not([data-tooltip-persist="true"])', window.eoxiaJS.tooltip.onOut ); + }; + + window.eoxiaJS.tooltip.onEnter = function( event ) { + window.eoxiaJS.tooltip.display( $( this ) ); + }; + + window.eoxiaJS.tooltip.onOut = function( event ) { + window.eoxiaJS.tooltip.remove( $( this ) ); + }; + + /** + * [description] + * + * @memberof EO_Framework_Tooltip + * + * @param {void} event [description] + * @returns {void} [description] + */ + window.eoxiaJS.tooltip.display = function( element ) { + var direction = ( $( element ).data( 'direction' ) ) ? $( element ).data( 'direction' ) : 'top'; + var el = $( '' + $( element ).attr( 'aria-label' ) + '' ); + var pos = $( element ).position(); + var offset = $( element ).offset(); + $( element )[0].tooltipElement = el; + $( 'body' ).append( $( element )[0].tooltipElement ); + + if ( $( element ).data( 'color' ) ) { + el.addClass( 'tooltip-' + $( element ).data( 'color' ) ); + } + + var top = 0; + var left = 0; + + switch( $( element ).data( 'direction' ) ) { + case 'left': + top = ( offset.top - ( el.outerHeight() / 2 ) + ( $( element ).outerHeight() / 2 ) ) + 'px'; + left = ( offset.left - el.outerWidth() - 10 ) + 3 + 'px'; + break; + case 'right': + top = ( offset.top - ( el.outerHeight() / 2 ) + ( $( element ).outerHeight() / 2 ) ) + 'px'; + left = offset.left + $( element ).outerWidth() + 8 + 'px'; + break; + case 'bottom': + top = ( offset.top + $( element ).height() + 10 ) + 10 + 'px'; + left = ( offset.left - ( el.outerWidth() / 2 ) + ( $( element ).outerWidth() / 2 ) ) + 'px'; + break; + case 'top': + top = offset.top - el.outerHeight() - 4 + 'px'; + left = ( offset.left - ( el.outerWidth() / 2 ) + ( $( element ).outerWidth() / 2 ) ) + 'px'; + break; + default: + top = offset.top - el.outerHeight() - 4 + 'px'; + left = ( offset.left - ( el.outerWidth() / 2 ) + ( $( element ).outerWidth() / 2 ) ) + 'px'; + break; + } + + el.css( { + 'top': top, + 'left': left, + 'opacity': 1 + } ); + + $( element ).on("remove", function() { + $( $( element )[0].tooltipElement ).remove(); + + } ); + }; + + /** + * [description] + * + * @memberof EO_Framework_Tooltip + * + * @param {void} event [description] + * @returns {void} [description] + */ + window.eoxiaJS.tooltip.remove = function( element ) { + if ( $( element )[0] && $( element )[0].tooltipElement ) { + $( $( element )[0].tooltipElement ).remove(); + } + }; +} + +/** + * Initialise l'objet "task" ainsi que la méthode "init" obligatoire pour la bibliothèque EoxiaJS. + * + * @since 1.0.0 + * @version 1.0.0 + */ +window.eoxiaJS.task = {}; + +/** + * La méthode appelée automatiquement par la bibliothèque EoxiaJS. + * + * @since 1.0.0 + * @version 1.0.0 + * + * @return {void} + */ +window.eoxiaJS.task.init = function() { + window.eoxiaJS.task.event(); +}; + +/** + * La méthode contenant tous les événements pour le task. + * + * @since 1.0.0 + * @version 1.0.0 + * + * @return {void} + */ +window.eoxiaJS.task.event = function() { + $( document ).on( 'click', '.auto-fill-timespent', window.eoxiaJS.task.addTimeSpent ); + $( document ).on( 'click', '.auto-fill-timespent-project', window.eoxiaJS.task.divideTimeSpent ); + $( document ).on( 'click', '.show-only-favorite-tasks', window.eoxiaJS.task.showOnlyFavoriteTasks ); +}; + +/** + * Remplit automatiquement le temps à pointer disponible sur une tâche + * + * @since 1.0.0 + * @version 1.0.0 + * + * @param {MouseEvent} event [description] + * @return {void} + */ +window.eoxiaJS.task.addTimeSpent = function( event ) { + let nonConsumedMinutes = $('.non-consumed-time-minute').val() + let nonConsumedHours = $('.non-consumed-time-hour').val() + $('.inputhour').val('') + $('.inputminute').val('') + $(this).closest('.duration').find('.inputhour').val(nonConsumedHours) + $(this).closest('.duration').find('.inputminute').val(nonConsumedMinutes) +}; + +/** + * Répartit automatiquement le temps à pointer disponible entre les tâches du projet + * + * @since 1.0.0 + * @version 1.0.0 + * + * @param {MouseEvent} event [description] + * @return {void} + */ +window.eoxiaJS.task.divideTimeSpent = function( event ) { + let projectId = $(this).closest('.project-line').attr('id') + + let taskMinute = 0 + let taskHour = 0 + + let nonConsumedMinutes = $('.non-consumed-time-minute').val() + let nonConsumedHours = $('.non-consumed-time-hour').val() + let totalTimeInMinutes = +nonConsumedMinutes + +nonConsumedHours*60 + + let taskLinkedCounter = $('.'+projectId).length + let minutesToSpend = parseInt(totalTimeInMinutes/taskLinkedCounter) + + $('.inputhour').val('') + $('.inputminute').val('') + + $('.'+projectId).each(function() { + taskHour = parseInt(minutesToSpend/60) + taskMinute = minutesToSpend%60 + + $(this).find('.inputhour').val(taskHour) + $(this).find('.inputminute').val(taskMinute) + }) +}; + +/** + * Active/désactive la configuration pour n'afficher que les tâches favorites + * + * @since 1.0.0 + * @version 1.0.0 + * + * @param {MouseEvent} event [description] + * @return {void} + */ +window.eoxiaJS.task.showOnlyFavoriteTasks = function( event ) { + let token = $('.id-container').find('input[name="token"]').val(); + let querySeparator = '?'; + + document.URL.match(/\?/) ? querySeparator = '&' : 1 + + $.ajax({ + url: document.URL + querySeparator + "action=showOnlyFavoriteTasks&token=" + token, + type: "POST", + processData: false, + contentType: false, + success: function ( resp ) { + window.location.reload() + }, + error: function ( ) { + } + }); +}; + +/** + * Initialise l'objet "menu" ainsi que la méthode "init" obligatoire pour la bibliothèque EoxiaJS. + * + * @since 1.0.0 + * @version 1.0.0 + */ +window.eoxiaJS.menu = {}; + +/** + * La méthode appelée automatiquement par la bibliothèque EoxiaJS. + * + * @since 1.0.0 + * @version 1.0.0 + * + * @return {void} + */ +window.eoxiaJS.menu.init = function() { + window.eoxiaJS.menu.event(); +}; + +/** + * La méthode contenant tous les événements pour le migration. + * + * @since 1.0.0 + * @version 1.0.0 + * + * @return {void} + */ +window.eoxiaJS.menu.event = function() { + $(document).on( 'click', ' .blockvmenu', window.eoxiaJS.menu.toggleMenu); + $(document).ready(function() { window.eoxiaJS.menu.setMenu()}); +} + +/** + * Action Toggle main menu. + * + * @since 8.5.0 + * @version 9.4.0 + * + * @return {void} + */ +window.eoxiaJS.menu.toggleMenu = function() { + + var menu = $(this).closest('#id-left').find('a.vmenu, font.vmenudisabled, span.vmenu'); + var elementParent = $(this).closest('#id-left').find('div.vmenu') + var text = ''; + + if ($(this).find('span.vmenu').find('.fa-chevron-circle-left').length > 0) { + + menu.each(function () { + text = $(this).html().split(''); + if (text[1].match(/>/)) { + text[1] = text[1].replace(/>/, '') + } + $(this).attr('title', text[1]) + $(this).html(text[0]); + }); + + elementParent.css('width', '30px'); + elementParent.find('.blockvmenusearch').hide(); + $('span.vmenu').attr('title', ' Agrandir le menu') + + $('span.vmenu').html($('span.vmenu').html()); + + $(this).find('span.vmenu').find('.fa-chevron-circle-left').removeClass('fa-chevron-circle-left').addClass('fa-chevron-circle-right'); + localStorage.setItem('maximized', 'false') + + } else if ($(this).find('span.vmenu').find('.fa-chevron-circle-right').length > 0) { + + menu.each(function () { + $(this).html($(this).html().replace('>','') + ' ' + $(this).attr('title')); + }); + + elementParent.css('width', '188px'); + elementParent.find('.blockvmenusearch').show(); + $('div.menu_titre').attr('style', 'width: 188px !important; cursor : pointer' ) + $('span.vmenu').attr('title', ' Réduire le menu') + $('span.vmenu').html(' Réduire le menu'); + + localStorage.setItem('maximized', 'true') + + $(this).find('span.vmenu').find('.fa-chevron-circle-right').removeClass('fa-chevron-circle-right').addClass('fa-chevron-circle-left'); + } +}; + +/** + * Action set menu. + * + * @since 8.5.0 + * @version 9.0.1 + * + * @return {void} + */ +window.eoxiaJS.menu.setMenu = function() { + if ($('.blockvmenu.blockvmenufirst').html().match(/dolisirh/)) { + $('span.vmenu').find('.fa-chevron-circle-left').parent().parent().parent().attr('style', 'cursor:pointer ! important') + + if (localStorage.maximized == 'false') { + $('#id-left').attr('style', 'display:none !important') + } + + if (localStorage.maximized == 'false') { + var text = ''; + var menu = $('#id-left').find('a.vmenu, font.vmenudisabled, span.vmenu'); + var elementParent = $(document).find('div.vmenu') + + menu.each(function () { + text = $(this).html().split(''); + $(this).attr('title', text[1]) + $(this).html(text[0]); + }); + + $('#id-left').attr('style', 'display:block !important') + $('div.menu_titre').attr('style', 'width: 50px !important') + $('span.vmenu').attr('title', ' Agrandir le menu') + + $('span.vmenu').html($('span.vmenu').html()) + $('span.vmenu').find('.fa-chevron-circle-left').removeClass('fa-chevron-circle-left').addClass('fa-chevron-circle-right'); + + elementParent.css('width', '30px'); + elementParent.find('.blockvmenusearch').hide(); + } + localStorage.setItem('currentString', '') + localStorage.setItem('keypressNumber', 0) + } +}; + +/** + * Initialise l'objet "signature" ainsi que la méthode "init" obligatoire pour la bibliothèque EoxiaJS. + * + * @since 1.4.0 + * @version 1.4.0 + */ +window.eoxiaJS.signature = {}; + +/** + * Initialise le canvas signature + * + * @since 1.4.0 + * @version 1.4.0 + */ +window.eoxiaJS.signature.canvas; + +/** + * Initialise le boutton signature + * + * @since 1.4.0 + * @version 1.4.0 + */ +window.eoxiaJS.signature.buttonSignature; + +/** + * La méthode appelée automatiquement par la bibliothèque EoxiaJS. + * + * @since 1.4.0 + * @version 1.4.0 + * + * @return {void} + */ +window.eoxiaJS.signature.init = function() { + window.eoxiaJS.signature.event(); +}; + +/** + * La méthode contenant tous les événements pour la signature. + * + * @since 1.4.0 + * @version 1.4.0 + * + * @return {void} + */ +window.eoxiaJS.signature.event = function() { + $( document ).on( 'click', '.signature-erase', window.eoxiaJS.signature.clearCanvas ); + $( document ).on( 'click', '.signature-validate', window.eoxiaJS.signature.createSignature ); + $( document ).on( 'click', '.auto-download', window.eoxiaJS.signature.autoDownloadSpecimen ); +}; + +/** + * Open modal signature + * + * @since 1.4.0 + * @version 1.4.0 + * + * @return {void} + */ +window.eoxiaJS.signature.modalSignatureOpened = function( triggeredElement ) { + window.eoxiaJS.signature.buttonSignature = triggeredElement; + + var ratio = Math.max( window.devicePixelRatio || 1, 1 ); + + window.eoxiaJS.signature.canvas = document.querySelector('#modal-signature' + triggeredElement.attr('value') + ' canvas' ); + + window.eoxiaJS.signature.canvas.signaturePad = new SignaturePad( window.eoxiaJS.signature.canvas, { + penColor: "rgb(0, 0, 0)" + } ); + + window.eoxiaJS.signature.canvas.width = window.eoxiaJS.signature.canvas.offsetWidth * ratio; + window.eoxiaJS.signature.canvas.height = window.eoxiaJS.signature.canvas.offsetHeight * ratio; + window.eoxiaJS.signature.canvas.getContext( "2d" ).scale( ratio, ratio ); + window.eoxiaJS.signature.canvas.signaturePad.clear(); + + var signature_data = $( '#signature_data' + triggeredElement.attr('value') ).val(); + window.eoxiaJS.signature.canvas.signaturePad.fromDataURL(signature_data); +}; + +/** + * Action Clear sign + * + * @since 1.4.0 + * @version 1.4.0 + * + * @return {void} + */ +window.eoxiaJS.signature.clearCanvas = function( event ) { + var canvas = $( this ).closest( '.modal-signature' ).find( 'canvas' ); + canvas[0].signaturePad.clear(); +}; + +/** + * Action create signature + * + * @since 1.4.0 + * @version 1.4.0 + * + * @return {void} + */ +window.eoxiaJS.signature.createSignature = function() { + let elementSignatory = $(this).attr('value'); + let elementRedirect = ''; + let elementCode = ''; + let elementZone = $(this).find('#zone' + elementSignatory).attr('value'); + let elementConfCAPTCHA = $('#confCAPTCHA').val(); + let actionContainerSuccess = $('.noticeSignatureSuccess'); + var signatoryIDPost = ''; + if (elementSignatory !== 0) { + signatoryIDPost = '&signatoryID=' + elementSignatory; + } + + if ( ! $(this).closest( '.wpeo-modal' ).find( 'canvas' )[0].signaturePad.isEmpty() ) { + var signature = $(this).closest( '.wpeo-modal' ).find( 'canvas' )[0].toDataURL(); + } + + let token = $('.modal-signature').find('input[name="token"]').val(); + + var url = ''; + var type = ''; + if (elementZone == "private") { + url = document.URL + '&action=addSignature' + signatoryIDPost + '&token=' + token; + type = "POST" + } else { + url = document.URL + '&action=addSignature' + signatoryIDPost + '&token=' + token; + type = "POST"; + } + + if (elementConfCAPTCHA == 1) { + elementCode = $('#securitycode').val(); + let elementSessionCode = $('#sessionCode').val(); + if (elementSessionCode != elementCode) { + elementRedirect = $('#redirectSignatureError').val(); + } + } else { + elementRedirect = $(this).find('#redirect' + elementSignatory).attr('value'); + } + + $.ajax({ + url: url, + type: type, + processData: false, + contentType: 'application/octet-stream', + data: JSON.stringify({ + signature: signature, + code: elementCode + }), + success: function( resp ) { + if (elementZone == "private") { + actionContainerSuccess.html($(resp).find('.noticeSignatureSuccess .all-notice-content')); + actionContainerSuccess.removeClass('hidden'); + $('.signatures-container').html($(resp).find('.signatures-container')); + } else { + window.location.replace(elementRedirect); + } + }, + error: function ( ) { + alert('Error') + } + }); +}; + +/** + * Download signature + * + * @since 1.4.0 + * @version 1.4.0 + * + * @return {void} + */ +window.eoxiaJS.signature.download = function(fileUrl, filename) { + var a = document.createElement("a"); + a.href = fileUrl; + a.setAttribute("download", filename); + a.click(); +} + +/** + * Auto Download signature specimen + * + * @since 1.4.0 + * @version 1.4.0 + * + * @return {void} + */ +window.eoxiaJS.signature.autoDownloadSpecimen = function( event ) { + let element = $(this).closest('.file-generation') + let token = $('.digirisk-signature-container').find('input[name="token"]').val(); + let url = document.URL + '&action=builddoc&token=' + token + $.ajax({ + url: url, + type: "POST", + success: function ( ) { + let filename = element.find('.specimen-name').attr('value') + let path = element.find('.specimen-path').attr('value') + + window.eoxiaJS.signature.download(path + filename, filename); + $.ajax({ + url: document.URL + '&action=remove_file&token=' + token, + type: "POST", + success: function ( ) { + }, + error: function ( ) { + } + }); + }, + error: function ( ) { + } + }); +}; + +/** + * Initialise l'objet "keyEvent" ainsi que la méthode "init" obligatoire pour la bibliothèque EoxiaJS. + * + * @since 1.4.0 + * @version 1.4.0 + */ +window.eoxiaJS.keyEvent = {}; + +/** + * La méthode appelée automatiquement par la bibliothèque EoxiaJS. + * + * @since 1.4.0 + * @version 1.4.0 + * + * @return {void} + */ +window.eoxiaJS.keyEvent.init = function() { + window.eoxiaJS.keyEvent.event(); +}; + +/** + * La méthode contenant tous les événements pour le migration. + * + * @since 1.4.0 + * @version 1.4.0 + * + * @return {void} + */ +window.eoxiaJS.keyEvent.event = function() { + $( document ).on( 'keydown', window.eoxiaJS.keyEvent.keyup ); +} + +/** + * Action modal close & validation with key events + * + * @since 1.4.0 + * @version 1.4.0 + * + * @return {void} + */ +window.eoxiaJS.keyEvent.keyup = function( event ) { + if ( 'Escape' === event.key ) { + $(this).find('.modal-active .modal-close .fas.fa-times').first().click(); + } +}; + + diff --git a/js/index.php b/js/index.php new file mode 100644 index 0000000..17927e6 --- /dev/null +++ b/js/index.php @@ -0,0 +1,2 @@ +e?(r&&(clearTimeout(r),r=null),h=c,s=t.apply(o,n),r||(o=n=null)):r||!1===i.trailing||(r=setTimeout(a,d)),s}}function o(t,e){var n=this,s=e||{};this.velocityFilterWeight=s.velocityFilterWeight||.7,this.minWidth=s.minWidth||.5,this.maxWidth=s.maxWidth||2.5,this.throttle="throttle"in s?s.throttle:16,this.minDistance="minDistance"in s?s.minDistance:5,this.throttle?this._strokeMoveUpdate=i(o.prototype._strokeUpdate,this.throttle):this._strokeMoveUpdate=o.prototype._strokeUpdate,this.dotSize=s.dotSize||function(){return(this.minWidth+this.maxWidth)/2},this.penColor=s.penColor||"black",this.backgroundColor=s.backgroundColor||"rgba(0,0,0,0)",this.onBegin=s.onBegin,this.onEnd=s.onEnd,this._canvas=t,this._ctx=t.getContext("2d"),this.clear(),this._handleMouseDown=function(t){1===t.which&&(n._mouseButtonDown=!0,n._strokeBegin(t))},this._handleMouseMove=function(t){n._mouseButtonDown&&n._strokeMoveUpdate(t)},this._handleMouseUp=function(t){1===t.which&&n._mouseButtonDown&&(n._mouseButtonDown=!1,n._strokeEnd(t))},this._handleTouchStart=function(t){if(1===t.targetTouches.length){var e=t.changedTouches[0];n._strokeBegin(e)}},this._handleTouchMove=function(t){t.preventDefault();var e=t.targetTouches[0];n._strokeMoveUpdate(e)},this._handleTouchEnd=function(t){t.target===n._canvas&&(t.preventDefault(),n._strokeEnd(t))},this.on()}return t.prototype.velocityFrom=function(t){return this.time!==t.time?this.distanceTo(t)/(this.time-t.time):1},t.prototype.distanceTo=function(t){return Math.sqrt(Math.pow(this.x-t.x,2)+Math.pow(this.y-t.y,2))},t.prototype.equals=function(t){return this.x===t.x&&this.y===t.y&&this.time===t.time},e.prototype.length=function(){for(var t=0,e=void 0,i=void 0,o=0;o<=10;o+=1){var n=o/10,s=this._point(n,this.startPoint.x,this.control1.x,this.control2.x,this.endPoint.x),r=this._point(n,this.startPoint.y,this.control1.y,this.control2.y,this.endPoint.y);if(o>0){var h=s-e,a=r-i;t+=Math.sqrt(h*h+a*a)}e=s,i=r}return t},e.prototype._point=function(t,e,i,o,n){return e*(1-t)*(1-t)*(1-t)+3*i*(1-t)*(1-t)*t+3*o*(1-t)*t*t+n*t*t*t},o.prototype.clear=function(){var t=this._ctx,e=this._canvas;t.fillStyle=this.backgroundColor,t.clearRect(0,0,e.width,e.height),t.fillRect(0,0,e.width,e.height),this._data=[],this._reset(),this._isEmpty=!0},o.prototype.fromDataURL=function(t){var e=this,i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},o=new Image,n=i.ratio||window.devicePixelRatio||1,s=i.width||this._canvas.width/n,r=i.height||this._canvas.height/n;this._reset(),o.src=t,o.onload=function(){e._ctx.drawImage(o,0,0,s,r)},this._isEmpty=!1},o.prototype.toDataURL=function(t){var e;switch(t){case"image/svg+xml":return this._toSVG();default:for(var i=arguments.length,o=Array(i>1?i-1:0),n=1;n2,i=this.points[0];if(!e&&i&&this._drawDot(i),i){var o=this._data[this._data.length-1],n=o[o.length-1];i.equals(n)||o.push({x:i.x,y:i.y,time:i.time,color:this.penColor})}"function"==typeof this.onEnd&&this.onEnd(t)},o.prototype._handleMouseEvents=function(){this._mouseButtonDown=!1,this._canvas.addEventListener("mousedown",this._handleMouseDown),this._canvas.addEventListener("mousemove",this._handleMouseMove),document.addEventListener("mouseup",this._handleMouseUp)},o.prototype._handleTouchEvents=function(){this._canvas.style.msTouchAction="none",this._canvas.style.touchAction="none",this._canvas.addEventListener("touchstart",this._handleTouchStart),this._canvas.addEventListener("touchmove",this._handleTouchMove),this._canvas.addEventListener("touchend",this._handleTouchEnd)},o.prototype._reset=function(){this.points=[],this._lastVelocity=0,this._lastWidth=(this.minWidth+this.maxWidth)/2,this._ctx.fillStyle=this.penColor},o.prototype._createPoint=function(e,i,o){var n=this._canvas.getBoundingClientRect();return new t(e-n.left,i-n.top,o||(new Date).getTime())},o.prototype._addPoint=function(t){var i=this.points,o=void 0;if(i.push(t),i.length>2){3===i.length&&i.unshift(i[0]),o=this._calculateCurveControlPoints(i[0],i[1],i[2]);var n=o.c2;o=this._calculateCurveControlPoints(i[1],i[2],i[3]);var s=o.c1,r=new e(i[1],n,s,i[2]),h=this._calculateCurveWidths(r);return i.shift(),{curve:r,widths:h}}return{}},o.prototype._calculateCurveControlPoints=function(e,i,o){var n=e.x-i.x,s=e.y-i.y,r=i.x-o.x,h=i.y-o.y,a={x:(e.x+i.x)/2,y:(e.y+i.y)/2},c={x:(i.x+o.x)/2,y:(i.y+o.y)/2},d=Math.sqrt(n*n+s*s),l=Math.sqrt(r*r+h*h),u=a.x-c.x,v=a.y-c.y,p=l/(d+l),_={x:c.x+u*p,y:c.y+v*p},y=i.x-_.x,f=i.y-_.y;return{c1:new t(a.x+y,a.y+f),c2:new t(c.x+y,c.y+f)}},o.prototype._calculateCurveWidths=function(t){var e=t.startPoint,i=t.endPoint,o={start:null,end:null},n=this.velocityFilterWeight*i.velocityFrom(e)+(1-this.velocityFilterWeight)*this._lastVelocity,s=this._strokeWidth(n);return o.start=this._lastWidth,o.end=s,this._lastVelocity=n,this._lastWidth=s,o},o.prototype._strokeWidth=function(t){return Math.max(this.maxWidth/(t+1),this.minWidth)},o.prototype._drawPoint=function(t,e,i){var o=this._ctx;o.moveTo(t,e),o.arc(t,e,i,0,2*Math.PI,!1),this._isEmpty=!1},o.prototype._drawCurve=function(t,e,i){var o=this._ctx,n=i-e,s=Math.floor(t.length());o.beginPath();for(var r=0;r1)for(var r=0;r',a=r.innerHTML;if(void 0===a){var c=document.createElement("dummy"),d=r.childNodes;c.innerHTML="";for(var l=0;l";return"data:image/svg+xml;base64,"+btoa(u)},o.prototype.fromData=function(t){var e=this;this.clear(),this._fromData(t,function(t,i){return e._drawCurve(t,i.start,i.end)},function(t){return e._drawDot(t)}),this._data=t},o.prototype.toData=function(){return this._data},o}); diff --git a/langs/en_US/dolisirh.lang b/langs/en_US/dolisirh.lang new file mode 100644 index 0000000..d9d3827 --- /dev/null +++ b/langs/en_US/dolisirh.lang @@ -0,0 +1,74 @@ +# Copyright (C) 2020 SuperAdmin +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# +# Generic +# + +# Module label 'ModuleDolisirhName' +ModuleDolisirhName = Dolisirh +# Module description 'ModuleDolisirhDesc' +ModuleDolisirhDesc = Dolisirh description + +# +# Admin page +# +DolisirhSetup = Dolisirh setup +Settings = Settings +DolisirhSetupPage = Dolisirh setup page +DOLISIRH_MYPARAM1 = My param 1 +DOLISIRH_MYPARAM1Tooltip = My param 1 tooltip +DOLISIRH_MYPARAM2=My param 2 +DOLISIRH_MYPARAM2Tooltip=My param 2 tooltip + + +# +# About page +# +About = About +DolisirhAbout = About Dolisirh +DolisirhAboutPage = Dolisirh about page + +# +# Sample page +# +MyPageName = My page name + +# +# Sample widget +# +MyWidget = My widget +MyWidgetDescription = My widget description + +# +# module dolisirh +# +DescriptionTask = Realize from the invoice +MessageInfo = Task successfully created +MessageInfoNoCreate = Task not created +MessageInfoNoCreateProject = No task was created because the project is not linked +MessageInfoNoCreateTime = No task has been created because the service has no time +MessageInfoNoCreatedate = No task has been created because the service has no date +ErrorNoProject = Project not linked +ErrorDateStart = No date start +ErrorDateEnd = No date end +ErrorServiceTime = Service(s) time is zero +MessageTimeSpentCreate = Time spent created +MessageNoTaskLink = No task affected, no time passed available + +# +# Setup Page +# +DOLISIRH_DEFAUT_TICKET_TIME = Default time spent diff --git a/langs/en_US/index.php b/langs/en_US/index.php new file mode 100644 index 0000000..17927e6 --- /dev/null +++ b/langs/en_US/index.php @@ -0,0 +1,2 @@ + +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# +# Générique +# + +# Module label 'ModuleDoliSIRHName' +ModuleDoliSIRHName = DoliSIRH +# Module description 'ModuleDoliSIRHDesc' +ModuleDoliSIRHDesc = Description de DoliSIRH + +# +# Page d'administration +# +DoliSIRHSetup = Configuration du module DoliSIRH +Settings = Réglages +DoliSIRHSetupPage = Page de configuration du module DoliSIRH +DOLISIRH_DEFAUT_TICKET_TIME = Temps passé par défaut + +# +# Page À propos +# +About = À propos +DoliSIRHAbout = À propos de DoliSIRH +DoliSIRHAboutPage = Page à propos de DoliSIRH + +# +# DoliSIRH +# + +# Right - Droit +LireDoliSIRH = Consulter DoliSIRH +ReadDoliSIRH = Consulter DoliSIRH (read) +ReadAdminPage = Accéder à la configuration du module DoliSIRH + +# Data - Donnée +DescriptionTask = Réalisé depuis la facture +MessageInfo = Tâche créée avec succès +MessageInfoNoCreate = Aucune tâche n'a été créée +MessageInfoNoCreateProject = Aucune tâche n'a été créée car le projet n'est pas lié +MessageInfoNoCreateTime = Aucune tâche n'a été créée car le service n'a pas de temps +MessageInfoNoCreatedate = Aucune tâche n'a été créée car le service n'a pas de date +ErrorNoProject = Projet non lié +ErrorDateStart = Pas de date de début +ErrorDateEnd = Pas de date de fin +ErrorServiceTime = Le temps du(des) service(s) est nul +MessageTimeSpentCreate = Temps consommé crée +MessageNoTaskLink = Pas de tâche affectée, pas de temps passé disponible +DoliSIRHTimeSpent = Rapport de temps passé +ActionAC_TEL_IN = Appel téléphonique entrant +ActionAC_TEL_OUT = Appel téléphonique sortant +DoliSIRHConfig = Configuration +DoliSIRHArea = Bienvenue sur DoliSIRH +DoliSIRHNumberOfModelFilesFound = Nombre de modèles par défaut + + + +# +# Temps consommé +# + +# Data - Donnée +Monday = Lundi +Tuesday = Mardi +Wednesday = Mercredi +Thursday = Jeudi +Friday = Vendredi +Saturday = Samedi +Sunday = Dimanche +Schedule = Horaires +MondayWorkingHours = Heures de travail du lundi +TuesdayWorkingHours = Heures de travail du mardi +WednesdayWorkingHours = Heures de travail du mercredi +ThursdayWorkingHours = Heures de travail du jeudi +FridayWorkingHours = Heures de travail du vendredi +SaturdayWorkingHours = Heures de travail du samedi +SundayWorkingHours = Heures de travail du dimanche +WorkingHoursFormatDesc = Renseigner le temps travaillé par jour (en minutes) +UserWorkingHours = Horaires de l'utilisateur +WrongWorkingHoursFormat = Mauvais format pour les heures travaillées : %s +UserWorkingHoursSaved = Horaires de l'utilisateurs sauvegardés +WorkingHours(min) = Temps travaillé (en minutes) +DayWorkTime = Temps du jour +NonConsumedTime = Temps non pointé +TimeSpent = Temps consommé +Holidays = Congés +PaidHolidays = Congés payés +SickLeave = Congés maladie +PublicHoliday = Jour férié +AdditionalHour = Heure supplémentaire +TooMuchTimeSpent = Vous avez pointé plus de temps que le temps non pointé disponible +AddTimeSpent = Pointage de temps +HumanResources = Ressources humaines +ProjectsAndTasks = Projets et tâches +HRProject = Projet Ressources Humaines +HRDescription = Projet comprenant les tâches liées aux ressources humaines +DoliSIRHNewTimeSpent = Temps consommé (en minutes) +DivideTimeIntoTasks = Répartir entre les tâches du projet +ShowOnlyFavoriteTasks = Afficher uniquement les tâches favorites +SpendMoreTimeThanPlanned = Pointer plus de temps que planifié +SpendMoreTimeThanPlannedDescription = Cette option permet de pointer plus de temps que le temps renseigné dans l'onglet "Horaires" de l'utilisateur +ConsumedTime = Temps pointé +ExpectedWorkedHoursMonth = Heures de travail prévues au mois de %s +SpentWorkedHoursMonth = Heures de travail passées du %s au %s +ConsumedWorkedHoursMonth = Heures de travail consommées du %s au %s +DiffSpentAndConsumedWorkedHoursMonth = Différence d'heures de travail passées/consommées du %s au %s +WarningShowOnlyFavoriteTasks = Attention quand l'option 'Afficher uniquement les tâches favorites' est activée, les valeurs totales récupèrent l'ensembles des tâches. +ExpectedWorkedHoursWeek = Heures de travail prévues du %s au %s +ThemeDashboardTimeSpent = Thème du Rapport de pointage de temps +TimeSpentList = Liste des temps consommés + + + +# +# Facture récurrente +# + +# Data - Donnée +RecurringInvoicesStatistics = Statistiques facture récurrentes +NumberOfRecurringBills = Nb de factures récurrentes +NumberOfRecurringBillsByMonth = Nb de factures récurrentes par mois +AmountOfRecurringBills = Montant de factures récurrentes +AmountOfRecurringBillsByMonthHT = Montant de factures récurrentes par mois (HT) +ExceededTimeSpentColor = Couleur temps consommés dépassés +NotExceededTimeSpentColor = Couleur temps consommés pas dépassés ou non pointés +PerfectTimeSpentColor = Couleur temps consommés parfait +InvoicesCategoriesArea = Espace des tags/catégories des factures + + + +# +# TimeSheetDocument - Fiche de navette +# + +# Right - Droit + +# Trigger - Déclencheur +TimeSheetDocumentGeneratedWithDolibarr = Fiche de navette générée avec Dolibarr + +# Mod Numbering - Modèle de numérotation +DoliSIRHTimeSheetDocumentDocumentNumberingModule = Modèle de numérotation des fiches de navette de DoliSIRH +DoliSIRHTimeSheetDocumentStandardModel = Renvoie le numéro sous la forme TSDn où n est un compteur séquentiel sans rupture et sans remise à 0. + +# ODT Template - Template ODT +DoliSIRHTemplateDocumentTimeSheetDocument = Modèle de documents des fiches de navette de DoliSIRH +TimeSheetDocumentCustomDoliSIRHTemplate = ODT custom des fiches de navette +TimeSheetDocumentDoliSIRHTemplate = ODT par défaut des fiches de navette + +# Data - Donnée +TimeSheetDocument = Fiche de Navette +timesheetdocument.odt = Navette ODT + + + +# +# TimeSheet - Navette +# + +# Right - Droit +ReadTimeSheet = Consulter la navette +CreateTimeSheet = Créer/Modifier la navette +DeleteTimeSheet = Supprimer la navette + +# Trigger - Déclencheur +TimeSheetDocumentGeneratedWithDolibarr = Fiche de navette générée avec Dolibarr +TimeSheetCreateTrigger = Création de la navette +TimeSheetModifyTrigger = Modification de la navette +TimeSheetDeleteTrigger = Suppression de la navette +TimeSheetUnValidateTrigger = Navette rouverte +TimeSheetValidateTrigger = Navette en attente de signature des signataires +TimeSheetLockedTrigger = Navette verrouillée - Prêt pour la génération du documuent +TimeSheetArchivedTrigger = Navette archivée +TimeSheetGenerateTrigger = Fiche navette générée +TimeSheetSentByMailTrigger = Email navette envoyé +TimeSheetLineCreateTrigger = Ligne de navette créée +TimeSheetLineModifyTrigger = Ligne de navette modifiée +TimeSheetLineDeleteTrigger = Ligne de navette supprimée + +# Mod Numbering - Modèle de numérotation +DoliSIRHTimeSheetDocumentDocumentNumberingModule = Modèle de numérotation des fiches de navette de DoliSIRH +DoliSIRHTimeSheetDocumentStandardModel = Renvoie le numéro sous la forme TSDn où n est un compteur séquentiel sans rupture et sans remise à 0. + +# ODT Template - Template ODT +DoliSIRHTemplateDocumentTimeSheetDocument = Modèle de documents des fiches de navette de DoliSIRH +TimeSheetDocumentCustomDoliSIRHTemplate = ODT custom des fiches de navette +TimeSheetDocumentDoliSIRHTemplate = ODT par défaut des fiches de navette + +# SetEventMessage - Notice info +TimeSheetMustBeDraft = La navette doit être en brouillon pour accéder à cette fonctionnalité +TimeSheetMustBeDraftToValidate = La navette est déjà validée +TimeSheetMustBeValidated = La navette doit être validée pour la rouvrir +TimeSheetMustBeValidatedToSign = La navette doit être validée pour que les signataires puissent signer +AllSignatoriesMustHaveSignedAndDiffTimeSetAt0 = Tous les signataires doivent avoir signé et l'utilisateur assigné doit avoir consommée toutes ses heures de travail pour verrouiller la navette +TimeSheetMustBeLockedToSendEmail = La navette doit être verrouillée pour envoyer un email +TimeSheetMustBeLocked = La navette doit être verrouillée afin de permettre la génération +TimeSheetMustBeLockedGenerated = La navette doit être verrouillée et le document généré afin de pouvoir l'archiver +ValidateTimeSheet = Valider la navette +ConfirmValidateTimeSheet = Êtes-vous sûr de vouloir valider la navette ?
La validation permet aux signataires de signer le document mais empêche l'ajout de nouveaux signataires ou la modification de la navette.

N'oubliez pas de vérifier les quantités des produits ou services liés. +ReOpenTimeSheet = Ouvrir à nouveau la navette +ConfirmReOpenTimeSheet = Êtes-vous sûr de vouloir rouvrir la navette ? La réouverture permet la modification de la navette et l'ajout de nouveaux signataires mais toutes les signatures du document seront perdues. +LockTimeSheet = Verrouiller la navette +ConfirmLockTimeSheet = Êtes-vous sûr de vouloir verrouiller la navette ?
Ce verrouillage permet de figer les données et la génération du document. +TimeSpentPerfect = Parfait, toutes tes heures de travail ont été consommées +TimeSpentMustBeCompleted = Attention, toutes tes heures de travail n'ont pas été consommées du %s au %s
Va sur ton pointage de temps du mois de %s pour arranger cela +TimeSpentDiff = Attention, tu as consommé trop d'heures de travail du %s au %s
Va sur ton pointage de temps du mois de %s pour arranger cela +GoToTimeSpent = Aller sur le pointage de temps du mois de %s +ErrorLinkedElementTimeSheetTimeSpent = Erreur liens entre navette et temps consommé
il existe déjà une navette lié au temps consommé affecté à l'utilisateur %s sur la période de %s au %s +RemoveFileTimeSheet = Supprimer la fiche navette +ConfirmRemoveFileTimeSheet = Êtes-vous sûr de vouloir supprimer la fiche navette ? La fiche navette sera supprimer ainsi que les liens entre la navette et le temps consommé.
De plus la navette retournera au status brouillon. +ErrorDateEndTimeSheet = Erreur date fin de navette %s supérieure à la date du jour %s +ErrorDateTimeSheet = Erreur date début de navette %s supérieure à la date fin de navette %s +ErrorConfigWorkingHours = Erreur : configuration des heures de travail manquantes +GoToWorkingHours = Aller sur la page Horaires de l'utilisateur %s + +# Data - Donnée +TimeSheet = Navette +NewTimeSheet = Nouvelle navette +ModifyTimeSheet = Modifer la navette +TimeSheetList = Liste des navettes +UserAssign = Utilisateur assigné +TimeSheetData = Données configurables de la navette +PrefillDate = Préremplir la date de début et de fin de la navette +PrefillDateDescription = Préremplissage de la date de début avec le premier jour du mois en cours et la date de fin avec le dernier jour du mois en cours +TimeSheetAttendants = Navette - Signataires +StatusDraft = Brouillon ( à valider) +Lock = Verrouiller +Locked = Verrouillée +Archive = Archiver +Archived = Archivée +ReOpenDoli = Rouvrir +ValidatePendingSignature = Validée (en attente de signature) +GoToLock = Verrouiller la navette +GoToValidate = Valider la navette +TIMESHEET_SOCIETY_ATTENDANT = Signataire interne +TIMESHEET_SOCIETY_RESPONSIBLE = Responsable +AddAttendantsConf = Ajouter des signataires +AddAttendantsDescription = Pouvoir ajouter des signataires pendant la réalisation de la navette
(par défaut il y a deux signataires, l'utilisateur assigné et son responsable hiéarchirque s'il est configuré dans son profil utilisateur) +TimesheetsCategoriesArea = Espace des tags/catégories des navettes +ConsumedWorkedDayMonth = Nombre de jour pointés : +ExpectedWorkedDayMonth = Nombre de jours ouvrés : +ExpectedWorkedHoursMonthTimeSheet = Heures de travail prévues du %s au %s +CheckDateEnd = Vérifier la date fin de navette +CheckDateEndDescription = Vérification si la date fin de navette est supérieure à la date du jour
(évite la création de temps consommés dans le futur) + + + +# +# DoliSIRHSignature - Signature +# + +# Trigger - Déclencheur +DoliSIRHAddAttendantTrigger = Ajout d'un signataire +DoliSIRHSignatureSignedTrigger = Signature du signataire effectuée +DoliSIRHSignaturePendingSignatureTrigger = Email envoyé, en attente de la signature du signataire +DoliSIRHSignatureAbsentTrigger = Signataire absent +DoliSIRHSignatureDeletedTrigger = Signataire supprimé + +# SetEventMessage - Notice info +DisclaimerSignatureTitle = Attention +AddSignatureSuccess = Signature du document réussie +AddSignatureSuccessText = La signature a bien été enregistrée pour le document +AddAttendantMessage = Ajout du signataire : +DeleteAttendantMessage = Suppression du signataire : +SignatureEvent = Le signataire a signé : %s +Attendant = Le signataire +SetAbsentAttendant = est absent + +# Status - Statut +Registered = Inscrit +SignatureRequest = Demande de signature +PendingSignature = En attente de signature +Denied = Refusé +Signed = Signé +Unsigned = Non signé +Absent = Absent +JustifiedAbsent = Absence justifiée + +# Header table - Entête de tableau +Role = Rôle +SignatureLink = Lien signature +SendMailDate = Date d'envoi d'email +SignatureDate = Date de signature +ActionsSignature = Actions + +# Data - Donnée +Attendants = Signataires +SendEmail = Envoyer un email +DeleteAttendant = Supprimer le signataire +Sign = Signer +Erase = Effacer +SocietyAttendant = Signataire interne +SocietyResponsible = Responsable +NoSocietyAttendants = Pas de signataires liés à cet objet. Pour ajouter des signataires, le statut doit être "Brouillon". +FileGenerated + + + +# +# Other +# + +# Data - Donnée +SendEmailAt = Envoi de l'email à +ErrorSetupEmail = Erreur de configuration des mails, vous n'avez pas configuré votre serveur d'envoi de mail +MealTicket = Ticket restaurant +JourneySubscription = Abonnement trajet +13thMonthBonus = Prime 13ème mois +SpecialBonus = Prime spéciale +MinimizeMenu = Réduire le menu +ErrorFileNotFound = Fichier non trouvé +NoData = N/A diff --git a/langs/fr_FR/index.php b/langs/fr_FR/index.php new file mode 100644 index 0000000..17927e6 --- /dev/null +++ b/langs/fr_FR/index.php @@ -0,0 +1,2 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file lib/dolisirh.lib.php + * \ingroup dolisirh + * \brief Library files with common functions for Dolisirh + */ + +/** + * Prepare admin pages header + * + * @return array + */ +function dolisirhAdminPrepareHead(): array +{ + global $conf, $langs; + + $langs->load("dolisirh@dolisirh"); + + $h = 0; + $head = array(); + + $head[$h][0] = dol_buildpath("/dolisirh/admin/project.php", 1); + $head[$h][1] = ' ' . $langs->trans("ProjectsAndTasks"); + $head[$h][2] = 'projecttasks'; + $h++; + + $head[$h][0] = dol_buildpath("/dolisirh/admin/timesheet.php", 1); + $head[$h][1] = ' ' . $langs->trans("TimeSheet"); + $head[$h][2] = 'timesheet'; + $h++; + + $head[$h][0] = dol_buildpath("/dolisirh/admin/timesheetdocument.php", 1); + $head[$h][1] = ' ' . $langs->trans("TimeSheetDocument"); + $head[$h][2] = 'timesheetdocument'; + $h++; + + $head[$h][0] = dol_buildpath("/dolisirh/admin/setup.php", 1); + $head[$h][1] = ' ' . $langs->trans("Settings"); + $head[$h][2] = 'settings'; + $h++; + + $head[$h][0] = dol_buildpath("/dolisirh/admin/about.php", 1); + $head[$h][1] = ' ' . $langs->trans("About"); + $head[$h][2] = 'about'; + $h++; + + complete_head_from_modules($conf, $langs, null, $head, $h, 'dolisirh'); + + return $head; +} diff --git a/lib/dolisirh_function.lib.php b/lib/dolisirh_function.lib.php new file mode 100644 index 0000000..65b5db2 --- /dev/null +++ b/lib/dolisirh_function.lib.php @@ -0,0 +1,2149 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** +* \file lib/dolisirh_function.lib.php +* \ingroup dolisirh +* \brief Library files with common functions for DoliCar + */ + +require_once DOL_DOCUMENT_ROOT . '/projet/class/task.class.php'; + +/** + * Add or delete task from favorite by the user + * + * @return float|int + */ +function toggleTaskFavorite($task_id, $user_id) +{ + global $db; + $task = new Task($db); + $task->fetch($task_id); + $task->fetchObjectLinked(); + + if (!empty($task->linkedObjects) && key_exists('user', $task->linkedObjects)) { + foreach($task->linkedObjects['user'] as $userLinked) { + if ($userLinked->id == $user_id) { + $link_exists = 1; + $task->deleteObjectLinked($user_id, 'user'); + } + } + } + + if (!$link_exists) { + $result = $task->add_object_linked('user', $user_id,'',''); + return $result; + } + return 0; +} + +/** + * \file dolisirh/lib/dolisirh_function.lib.php + * \ingroup dolisirh + * \brief Library files with common functions for DoliCar + */ + +/** + * Check if task is set to favorite by the user + * + * @return float|int + */ +function isTaskFavorite($task_id, $user_id) +{ + global $db; + $task = new Task($db); + $task->fetch($task_id); + $task->fetchObjectLinked(); + $link_exists = 0; + if (!empty($task->linkedObjects) && key_exists('user', $task->linkedObjects)) { + foreach($task->linkedObjects['user'] as $userLinked) { + if ($userLinked->id == $user_id) { + $link_exists = 1; + } + } + } + + return $link_exists; +} + +/** + * Return list of tasks for all projects or for one particular project + * Sort order is on project, then on position of task, and last on start date of first level task + * + * @param User $usert Object user to limit tasks affected to a particular user + * @param User $userp Object user to limit projects of a particular user and public projects + * @param int $projectid Project id + * @param int $socid Third party id + * @param int $mode 0=Return list of tasks and their projects, 1=Return projects and tasks if exists + * @param string $filteronproj Filter on project ref or label + * @param string $filteronprojstatus Filter on project status ('-1'=no filter, '0,1'=Draft+Validated only) + * @param string $morewherefilter Add more filter into where SQL request (must start with ' AND ...') + * @param string $filteronprojuser Filter on user that is a contact of project + * @param string $filterontaskuser Filter on user assigned to task + * @param array $extrafields Show additional column from project or task + * @param int $includebilltime Calculate also the time to bill and billed + * @param array $search_array_options Array of search + * @param int $loadextras Fetch all Extrafields on each task + * @return array Array of tasks + */ +function getFavoriteTasksArray($task_id = 0, $usert = null, $userp = null, $projectid = 0, $socid = 0, $mode = 0, $filteronproj = '', $filteronprojstatus = '-1', $morewherefilter = '', $filteronprojuser = 0, $filterontaskuser = 0, $extrafields = array(), $includebilltime = 0, $search_array_options = array(), $loadextras = 0) +{ + global $conf, $hookmanager, $db, $user; + require_once DOL_DOCUMENT_ROOT . '/projet/class/task.class.php'; + + $task = new Task($db); + $task->fetch($task_id); + + $tasks = array(); + + //print $usert.'-'.$userp.'-'.$projectid.'-'.$socid.'-'.$mode.'
'; + + // List of tasks (does not care about permissions. Filtering will be done later) + $sql = "SELECT "; + if ($filteronprojuser > 0 || $filterontaskuser > 0) { + $sql .= " DISTINCT"; // We may get several time the same record if user has several roles on same project/task + } + $sql .= " p.rowid as projectid, p.ref, p.title as plabel, p.public, p.fk_statut as projectstatus, p.usage_bill_time,"; + $sql .= " t.rowid as taskid, t.ref as taskref, t.label, t.description, t.fk_task_parent, t.duration_effective, t.progress, t.fk_statut as status,"; + $sql .= " t.dateo as date_start, t.datee as date_end, t.planned_workload, t.rang,"; + $sql .= " t.description, "; + $sql .= " t.budget_amount, "; + $sql .= " s.rowid as thirdparty_id, s.nom as thirdparty_name, s.email as thirdparty_email,"; + $sql .= " p.fk_opp_status, p.opp_amount, p.opp_percent, p.budget_amount as project_budget_amount"; + if (!empty($extrafields->attributes['projet']['label'])) { + foreach ($extrafields->attributes['projet']['label'] as $key => $val) { + $sql .= ($extrafields->attributes['projet']['type'][$key] != 'separate' ? ",efp.".$key." as options_".$key : ''); + } + } + if (!empty($extrafields->attributes['projet_task']['label'])) { + foreach ($extrafields->attributes['projet_task']['label'] as $key => $val) { + $sql .= ($extrafields->attributes['projet_task']['type'][$key] != 'separate' ? ",efpt.".$key." as options_".$key : ''); + } + } + if ($includebilltime) { + $sql .= ", SUM(tt.task_duration * ".$db->ifsql("invoice_id IS NULL", "1", "0").") as tobill, SUM(tt.task_duration * ".$db->ifsql("invoice_id IS NULL", "0", "1").") as billed"; + } + + $sql .= " FROM ".MAIN_DB_PREFIX."projet as p"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON p.fk_soc = s.rowid"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."projet_extrafields as efp ON (p.rowid = efp.fk_object)"; + + if ($mode == 0) { + if ($filteronprojuser > 0) { + $sql .= ", ".MAIN_DB_PREFIX."element_contact as ec"; + $sql .= ", ".MAIN_DB_PREFIX."c_type_contact as ctc"; + } + $sql .= ", ".MAIN_DB_PREFIX."projet_task as t"; + if ($includebilltime) { + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."projet_task_time as tt ON tt.fk_task = t.rowid"; + } + if ($filterontaskuser > 0) { + $sql .= ", ".MAIN_DB_PREFIX."element_contact as ec2"; + $sql .= ", ".MAIN_DB_PREFIX."c_type_contact as ctc2"; + } + if ($conf->global->DOLISIRH_SHOW_ONLY_FAVORITE_TASKS) { + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."element_element as elel ON (t.rowid = elel.fk_target AND elel.targettype='project_task')"; + } + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."projet_task_extrafields as efpt ON (t.rowid = efpt.fk_object)"; + $sql .= " WHERE p.entity IN (".getEntity('project').")"; + $sql .= " AND t.fk_projet = p.rowid"; + if ($conf->global->DOLISIRH_SHOW_ONLY_FAVORITE_TASKS) { + $sql .= " AND elel.fk_target = t.rowid"; + $sql .= " AND elel.fk_source = " . $user->id; + } + + } elseif ($mode == 1) { + if ($filteronprojuser > 0) { + $sql .= ", ".MAIN_DB_PREFIX."element_contact as ec"; + $sql .= ", ".MAIN_DB_PREFIX."c_type_contact as ctc"; + } + if ($filterontaskuser > 0) { + $sql .= ", ".MAIN_DB_PREFIX."projet_task as t"; + if ($includebilltime) { + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."projet_task_time as tt ON tt.fk_task = t.rowid"; + } + $sql .= ", ".MAIN_DB_PREFIX."element_contact as ec2"; + $sql .= ", ".MAIN_DB_PREFIX."c_type_contact as ctc2"; + } else { + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."projet_task as t on t.fk_projet = p.rowid"; + if ($includebilltime) { + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."projet_task_time as tt ON tt.fk_task = t.rowid"; + } + } + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."projet_task_extrafields as efpt ON (t.rowid = efpt.fk_object)"; + $sql .= " WHERE p.entity IN (".getEntity('project').")"; + } else { + return 'BadValueForParameterMode'; + } + + if ($filteronprojuser > 0) { + $sql .= " AND p.rowid = ec.element_id"; + $sql .= " AND ctc.rowid = ec.fk_c_type_contact"; + $sql .= " AND ctc.element = 'project'"; + $sql .= " AND ec.fk_socpeople = ".((int) $filteronprojuser); + $sql .= " AND ec.statut = 4"; + $sql .= " AND ctc.source = 'internal'"; + } + if ($filterontaskuser > 0) { + $sql .= " AND t.fk_projet = p.rowid"; + $sql .= " AND p.rowid = ec2.element_id"; + $sql .= " AND ctc2.rowid = ec2.fk_c_type_contact"; + $sql .= " AND ctc2.element = 'project_task'"; + $sql .= " AND ec2.fk_socpeople = ".((int) $filterontaskuser); + $sql .= " AND ec2.statut = 4"; + $sql .= " AND ctc2.source = 'internal'"; + } + if ($socid) { + $sql .= " AND p.fk_soc = ".((int) $socid); + } + if ($projectid) { + $sql .= " AND p.rowid IN (".$db->sanitize($projectid).")"; + } + if ($filteronproj) { + $sql .= natural_search(array("p.ref", "p.title"), $filteronproj); + } + if ($filteronprojstatus && $filteronprojstatus != '-1') { + $sql .= " AND p.fk_statut IN (".$db->sanitize($filteronprojstatus).")"; + } + if ($morewherefilter) { + $sql .= $morewherefilter; + } + // Add where from extra fields + $extrafieldsobjectkey = 'projet_task'; + $extrafieldsobjectprefix = 'efpt.'; + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; + // Add where from hooks + $parameters = array(); + $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook + $sql .= $hookmanager->resPrint; + if ($includebilltime) { + $sql .= " GROUP BY p.rowid, p.ref, p.title, p.public, p.fk_statut, p.usage_bill_time,"; + $sql .= " t.datec, t.dateo, t.datee, t.tms,"; + $sql .= " t.rowid, t.ref, t.label, t.description, t.fk_task_parent, t.duration_effective, t.progress, t.fk_statut,"; + $sql .= " t.dateo, t.datee, t.planned_workload, t.rang,"; + $sql .= " t.description, "; + $sql .= " t.budget_amount, "; + $sql .= " s.rowid, s.nom, s.email,"; + $sql .= " p.fk_opp_status, p.opp_amount, p.opp_percent, p.budget_amount"; + if (!empty($extrafields->attributes['projet']['label'])) { + foreach ($extrafields->attributes['projet']['label'] as $key => $val) { + $sql .= ($extrafields->attributes['projet']['type'][$key] != 'separate' ? ",efp.".$key : ''); + } + } + if (!empty($extrafields->attributes['projet_task']['label'])) { + foreach ($extrafields->attributes['projet_task']['label'] as $key => $val) { + $sql .= ($extrafields->attributes['projet_task']['type'][$key] != 'separate' ? ",efpt.".$key : ''); + } + } + } + + + $sql .= " ORDER BY p.ref, t.rang, t.dateo"; + + //print $sql;exit; + dol_syslog(get_class($task)."::getTasksArray", LOG_DEBUG); + $resql = $db->query($sql); + if ($resql) { + $num = $db->num_rows($resql); + $i = 0; + // Loop on each record found, so each couple (project id, task id) + while ($i < $num) { + $error = 0; + + $obj = $db->fetch_object($resql); + + if ((!$obj->public) && (is_object($userp))) { // If not public project and we ask a filter on project owned by a user + if (!$task->getUserRolesForProjectsOrTasks($userp, 0, $obj->projectid, 0)) { + $error++; + } + } + if (is_object($usert)) { // If we ask a filter on a user affected to a task + if (!$task->getUserRolesForProjectsOrTasks(0, $usert, $obj->projectid, $obj->taskid)) { + $error++; + } + } + + if (!$error) { + $tasks[$i] = new Task($db); + $tasks[$i]->id = $obj->taskid; + $tasks[$i]->ref = $obj->taskref; + $tasks[$i]->fk_project = $obj->projectid; + $tasks[$i]->projectref = $obj->ref; + $tasks[$i]->projectlabel = $obj->plabel; + $tasks[$i]->projectstatus = $obj->projectstatus; + + $tasks[$i]->fk_opp_status = $obj->fk_opp_status; + $tasks[$i]->opp_amount = $obj->opp_amount; + $tasks[$i]->opp_percent = $obj->opp_percent; + $tasks[$i]->budget_amount = $obj->budget_amount; + $tasks[$i]->project_budget_amount = $obj->project_budget_amount; + $tasks[$i]->usage_bill_time = $obj->usage_bill_time; + + $tasks[$i]->label = $obj->label; + $tasks[$i]->description = $obj->description; + $tasks[$i]->fk_parent = $obj->fk_task_parent; // deprecated + $tasks[$i]->fk_task_parent = $obj->fk_task_parent; + $tasks[$i]->duration = $obj->duration_effective; + $tasks[$i]->planned_workload = $obj->planned_workload; + + if ($includebilltime) { + $tasks[$i]->tobill = $obj->tobill; + $tasks[$i]->billed = $obj->billed; + } + + $tasks[$i]->progress = $obj->progress; + $tasks[$i]->fk_statut = $obj->status; + $tasks[$i]->public = $obj->public; + $tasks[$i]->date_start = $db->jdate($obj->date_start); + $tasks[$i]->date_end = $db->jdate($obj->date_end); + $tasks[$i]->rang = $obj->rang; + + $tasks[$i]->socid = $obj->thirdparty_id; // For backward compatibility + $tasks[$i]->thirdparty_id = $obj->thirdparty_id; + $tasks[$i]->thirdparty_name = $obj->thirdparty_name; + $tasks[$i]->thirdparty_email = $obj->thirdparty_email; + + if (!empty($extrafields->attributes['projet']['label'])) { + foreach ($extrafields->attributes['projet']['label'] as $key => $val) { + if ($extrafields->attributes['projet']['type'][$key] != 'separate') { + $tasks[$i]->{'options_'.$key} = $obj->{'options_'.$key}; + } + } + } + + if (!empty($extrafields->attributes['projet_task']['label'])) { + foreach ($extrafields->attributes['projet_task']['label'] as $key => $val) { + if ($extrafields->attributes['projet_task']['type'][$key] != 'separate') { + $tasks[$i]->{'options_'.$key} = $obj->{'options_'.$key}; + } + } + } + + if ($loadextras) { + $tasks[$i]->fetch_optionals(); + } + } + + $i++; + } + $db->free($resql); + } else { + dol_print_error($db); + } + + return $tasks; +} + +/** + * Output a task line into a pertime intput mode + * + * @param string $inc Line number (start to 0, then increased by recursive call) + * @param string $parent Id of parent task to show (0 to show all) + * @param User|null $fuser Restrict list to user if defined + * @param Task[] $lines Array of lines + * @param int $level Level (start to 0, then increased/decrease by recursive call) + * @param string $projectsrole Array of roles user has on project + * @param string $tasksrole Array of roles user has on task + * @param string $mine Show only task lines I am assigned to + * @param int $restricteditformytask 0=No restriction, 1=Enable add time only if task is assigned to me, 2=Enable add time only if tasks is assigned to me and hide others + * @param int $preselectedday Preselected day + * @param array $isavailable Array with data that say if user is available for several days for morning and afternoon + * @param int $oldprojectforbreak Old project id of last project break + * @param array $arrayfields Array of additional column + * @param Extrafields $extrafields Object extrafields + * @return array Array with time spent for $fuser for each day of week on tasks in $lines and substasks + */ +function dolisirhLinesPerDay(&$inc, $parent, $fuser, $lines, &$level, &$projectsrole, &$tasksrole, $mine, $restricteditformytask, $preselectedday, &$isavailable, $oldprojectforbreak = 0, $arrayfields = array(), $extrafields = null) +{ + global $conf, $db, $user, $langs; + global $form, $formother, $projectstatic, $taskstatic, $thirdpartystatic; + + $lastprojectid = 0; + $totalforeachday = array(); + $workloadforid = array(); + $lineswithoutlevel0 = array(); + + $numlines = count($lines); + + // Create a smaller array with sublevels only to be used later. This increase dramatically performances. + if ($parent == 0) { // Always and only if at first level + for ($i = 0; $i < $numlines; $i++) { + if ($lines[$i]->fk_task_parent) { + $lineswithoutlevel0[] = $lines[$i]; + } + } + } + + if (empty($oldprojectforbreak)) { + $oldprojectforbreak = (empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT) ? 0 : -1); // 0 to start break , -1 no break + } + + $restrictBefore = null; + + if (! empty($conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS)) { + require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; + $restrictBefore = dol_time_plus_duree(dol_now(), - $conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS, 'm'); + } + + //dol_syslog('projectLinesPerDay inc='.$inc.' preselectedday='.$preselectedday.' task parent id='.$parent.' level='.$level." count(lines)=".$numlines." count(lineswithoutlevel0)=".count($lineswithoutlevel0)); + for ($i = 0; $i < $numlines; $i++) { + if ($parent == 0) { + $level = 0; + } + + if ($lines[$i]->fk_task_parent == $parent) { + $obj = &$lines[$i]; // To display extrafields + + // If we want all or we have a role on task, we show it + if (empty($mine) || !empty($tasksrole[$lines[$i]->id])) { + //dol_syslog("projectLinesPerWeek Found line ".$i.", a qualified task (i have role or want to show all tasks) with id=".$lines[$i]->id." project id=".$lines[$i]->fk_project); + + if ($restricteditformytask == 2 && empty($tasksrole[$lines[$i]->id])) { // we have no role on task and we request to hide such cases + continue; + } + + // Break on a new project + if ($parent == 0 && $lines[$i]->fk_project != $lastprojectid) { + $lastprojectid = $lines[$i]->fk_project; + if ($preselectedday) { + $projectstatic->id = $lines[$i]->fk_project; + } + } + + if (empty($workloadforid[$projectstatic->id])) { + if ($preselectedday) { + $projectstatic->loadTimeSpent($preselectedday, 0, $fuser->id); // Load time spent from table projet_task_time for the project into this->weekWorkLoad and this->weekWorkLoadPerTask for all days of a week + $workloadforid[$projectstatic->id] = 1; + } + } + + $projectstatic->id = $lines[$i]->fk_project; + $projectstatic->ref = $lines[$i]->projectref; + $projectstatic->title = $lines[$i]->projectlabel; + $projectstatic->public = $lines[$i]->public; + $projectstatic->status = $lines[$i]->projectstatus; + + $taskstatic->id = $lines[$i]->id; + $taskstatic->ref = ($lines[$i]->ref ? $lines[$i]->ref : $lines[$i]->id); + $taskstatic->label = $lines[$i]->label; + $taskstatic->date_start = $lines[$i]->date_start; + $taskstatic->date_end = $lines[$i]->date_end; + + $thirdpartystatic->id = $lines[$i]->socid; + $thirdpartystatic->name = $lines[$i]->thirdparty_name; + $thirdpartystatic->email = $lines[$i]->thirdparty_email; + + $addcolspan = 2; + if (!empty($arrayfields['timeconsumed']['checked'])) { + $addcolspan++; + $addcolspan++; + } + foreach ($arrayfields as $key => $val) { + if ($val['checked'] && substr($key, 0, 5) == 'efpt.') { + $addcolspan++; + } + } + + if (empty($oldprojectforbreak) || ($oldprojectforbreak != -1 && $oldprojectforbreak != $projectstatic->id)) { + print ''."\n"; + print ''; + print $projectstatic->getNomUrl(1, '', 0, ''.$langs->transnoentitiesnoconv("YourRole").': '.$projectsrole[$lines[$i]->fk_project]); + if ($thirdpartystatic->id > 0) { + print ' - '.$thirdpartystatic->getNomUrl(1); + } + if ($projectstatic->title) { + print ' - '; + print ''.$projectstatic->title.''; + } + + print ''; + print ''; + if (!empty($conf->use_javascript_ajax)) { + print img_picto("Auto fill", 'rightarrow', "class='auto-fill-timespent-project' data-rowname='".$namef."' data-value='".($sign * $remaintopay)."'"); + } + print ' ' . $langs->trans('DivideTimeIntoTasks'); + print ''; + + print ''; + + print ''; + + print ''; + + print ''; + print ''; + } + + if ($oldprojectforbreak != -1) { + $oldprojectforbreak = $projectstatic->id; + } + + print ''."\n"; + + // User + /* + print ''; + print $fuser->getNomUrl(1, 'withproject', 'time'); + print ''; + */ + + // Project + if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) { + print ""; + if ($oldprojectforbreak == -1) { + print $projectstatic->getNomUrl(1, '', 0, $langs->transnoentitiesnoconv("YourRole").': '.$projectsrole[$lines[$i]->fk_project]); + } + print ""; + } + + // Thirdparty + if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) { + print ''; + if ($thirdpartystatic->id > 0) { + print $thirdpartystatic->getNomUrl(1, 'project', 10); + } + print ''; + } + + // Ref + print ''; + print ''; + for ($k = 0; $k < $level; $k++) { + print '
'; + } + print $taskstatic->getNomUrl(1, 'withproject', 'time'); + // Label task + print '
'; + print ''.$taskstatic->label.''; + for ($k = 0; $k < $level; $k++) { + print "
"; + } + print "\n"; + + // TASK extrafields + $extrafieldsobjectkey = 'projet_task'; + $extrafieldsobjectprefix = 'efpt.'; + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + + if (!empty($arrayfields['timeconsumed']['checked'])) { + // Time spent by everybody + print ''; + // $lines[$i]->duration is a denormalised field = summ of time spent by everybody for task. What we need is time consummed by user + if ($lines[$i]->duration) { + print ''; + print convertSecondToTime($lines[$i]->duration, 'allhourmin'); + print ''; + } else { + print '--:--'; + } + print "\n"; + + // Time spent by user + print ''; + $tmptimespent = $taskstatic->getSummaryOfTimeSpent($fuser->id); + if ($tmptimespent['total_duration']) { + print convertSecondToTime($tmptimespent['total_duration'], 'allhourmin'); + } else { + print '--:--'; + } + print "\n"; + } + + $disabledproject = 1; + $disabledtask = 1; + + // If at least one role for project + if ($lines[$i]->public || !empty($projectsrole[$lines[$i]->fk_project]) || $user->rights->projet->all->creer) { + $disabledproject = 0; + $disabledtask = 0; + } + // If $restricteditformytask is on and I have no role on task, i disable edit + if ($restricteditformytask && empty($tasksrole[$lines[$i]->id])) { + $disabledtask = 1; + } + + if ($restrictBefore && $preselectedday < $restrictBefore) { + $disabledtask = 1; + } + + // Select hour + print ''; + $tableCell = $form->selectDate($preselectedday, $lines[$i]->id, 1, 1, 2, "addtime", 0, 0, $disabledtask); + print $tableCell; + print ''; + + $cssonholiday = ''; + if (!$isavailable[$preselectedday]['morning'] && !$isavailable[$preselectedday]['afternoon']) { + $cssonholiday .= 'onholidayallday '; + } elseif (!$isavailable[$preselectedday]['morning']) { + $cssonholiday .= 'onholidaymorning '; + } elseif (!$isavailable[$preselectedday]['afternoon']) { + $cssonholiday .= 'onholidayafternoon '; + } + + global $daytoparse; + $tmparray = dol_getdate($daytoparse, true); // detail of current day + + $idw = ($tmparray['wday'] - (empty($conf->global->MAIN_START_WEEK) ? 0 : 1)); + global $numstartworkingday, $numendworkingday; + $cssweekend = ''; + if ((($idw + 1) < $numstartworkingday) || (($idw + 1) > $numendworkingday)) { // This is a day is not inside the setup of working days, so we use a week-end css. + $cssweekend = 'weekend'; + } + + // Duration + print ''; + $dayWorkLoad = $projectstatic->weekWorkLoadPerTask[$preselectedday][$lines[$i]->id]; + $totalforeachday[$preselectedday] += $dayWorkLoad; + + $alreadyspent = ''; + if ($dayWorkLoad > 0) { + $alreadyspent = convertSecondToTime($dayWorkLoad, 'allhourmin'); + } + + $idw = 0; + + $tableCell = ''; + $tableCell .= ''; + $tableCell .= ' + '; + //$tableCell.='   '; + if (!empty($conf->use_javascript_ajax)) { + $tableCell .= img_picto("Auto fill", 'rightarrow', "class='auto-fill-timespent' data-rowname='".$namef."' data-value='".($sign * $remaintopay)."'"); + } + $tableCell .= $form->select_duration($lines[$i]->id.'duration', '', $disabledtask, 'text', 0, 1); + //$tableCell.=' '; + print $tableCell; + + $modeinput = 'hours'; + + print ''; + + print ''; + + // Note + print ''; + print ''; + print ''; + + // Warning + print ''; + if ((!$lines[$i]->public) && $disabledproject) { + print $form->textwithpicto('', $langs->trans("UserIsNotContactOfProject")); + } elseif ($disabledtask) { + $titleassigntask = $langs->trans("AssignTaskToMe"); + if ($fuser->id != $user->id) { + $titleassigntask = $langs->trans("AssignTaskToUser", '...'); + } + + print $form->textwithpicto('', $langs->trans("TaskIsNotAssignedToUser", $titleassigntask)); + } + print ''; + + print "\n"; + } + + $inc++; + $level++; + if ($lines[$i]->id > 0) { + //var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level); + //var_dump($totalforeachday); + $ret = dolisirhLinesPerDay($inc, $lines[$i]->id, $fuser, ($parent == 0 ? $lineswithoutlevel0 : $lines), $level, $projectsrole, $tasksrole, $mine, $restricteditformytask, $preselectedday, $isavailable, $oldprojectforbreak, $arrayfields, $extrafields); + //var_dump('ret with parent='.$lines[$i]->id.' level='.$level); + //var_dump($ret); + foreach ($ret as $key => $val) { + $totalforeachday[$key] += $val; + } + //var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level.' + subtasks'); + //var_dump($totalforeachday); + } + $level--; + } else { + //$level--; + } + } + + return $totalforeachday; +} + +/** + * Prepare array with list of tabs + * + * @param string $mode Mode + * @param string $fuser Filter on user + * @return array Array of tabs to show + */ +function dolisirh_timesheet_prepare_head($mode, $fuser = null) +{ + global $langs, $conf, $user; + $h = 0; + $head = array(); + + $h = 0; + + $param = ''; + $param .= ($mode ? '&mode='.$mode : ''); + if (is_object($fuser) && $fuser->id > 0 && $fuser->id != $user->id) { + $param .= '&search_usertoprocessid='.$fuser->id; + } + + if (empty($conf->global->PROJECT_DISABLE_TIMESHEET_PERMONTH)) { + $head[$h][0] = DOL_URL_ROOT."/custom/dolisirh/view/timespent_month.php".($param ? '?'.$param : ''); + $head[$h][1] = $langs->trans("InputPerMonth"); + $head[$h][2] = 'inputpermonth'; + $h++; + } + + if (empty($conf->global->PROJECT_DISABLE_TIMESHEET_PERWEEK)) { + $head[$h][0] = DOL_URL_ROOT."/custom/dolisirh/view/timespent_week.php".($param ? '?'.$param : ''); + $head[$h][1] = $langs->trans("InputPerWeek"); + $head[$h][2] = 'inputperweek'; + $h++; + } + + if (empty($conf->global->PROJECT_DISABLE_TIMESHEET_PERTIME)) { + $head[$h][0] = DOL_URL_ROOT."/custom/dolisirh/view/timespent_day.php".($param ? '?'.$param : ''); + $head[$h][1] = $langs->trans("InputPerDay"); + $head[$h][2] = 'inputperday'; + $h++; + } + + complete_head_from_modules($conf, $langs, null, $head, $h, 'project_timesheet'); + + complete_head_from_modules($conf, $langs, null, $head, $h, 'project_timesheet', 'remove'); + + return $head; +} + +/** + * Sets object to given categories. + * + * Adds it to non existing supplied categories. + * Deletes object from existing categories not supplied (if remove_existing==true). + * Existing categories are left untouch. + * + * @param int[]|int $categories Category ID or array of Categories IDs + * @param string $type_categ Category type ('customer', 'supplier', 'website_page', ...) definied into const class Categorie type + * @param boolean $remove_existing True: Remove existings categories from Object if not supplies by $categories, False: let them + * @return int <0 if KO, >0 if OK + */ +function setCategoriesObject($categories, $type_categ = '', $remove_existing = true, $object) +{ + // Handle single category + if (!is_array($categories)) { + $categories = array($categories); + } + + dol_syslog(get_class($object)."::setCategoriesCommon Oject Id:".$object->id.' type_categ:'.$type_categ.' nb tag add:'.count($categories), LOG_DEBUG); + + require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; + + if (empty($type_categ)) { + dol_syslog(__METHOD__.': Type '.$type_categ.'is an unknown category type. Done nothing.', LOG_ERR); + return -1; + } + + // Get current categories + $c = new Categorie($object->db); + $existing = $c->containing($object->id, $type_categ, 'id'); + if ($remove_existing) { + // Diff + if (is_array($existing)) { + $to_del = array_diff($existing, $categories); + $to_add = array_diff($categories, $existing); + } else { + $to_del = array(); // Nothing to delete + $to_add = $categories; + } + } else { + $to_del = array(); // Nothing to delete + $to_add = array_diff($categories, $existing); + } + + $error = 0; + $ok = 0; + + // Process + foreach ($to_del as $del) { + if ($c->fetch($del) > 0) { + $result=$c->del_type($object, $type_categ); + if ($result < 0) { + $error++; + $object->error = $c->error; + $object->errors = $c->errors; + break; + } else { + $ok += $result; + } + } + } + foreach ($to_add as $add) { + if ($c->fetch($add) > 0) { + $result = $c->add_type($object, $type_categ); + if ($result < 0) { + $error++; + $object->error = $c->error; + $object->errors = $c->errors; + break; + } else { + $ok += $result; + } + } + } + + return $error ? -1 * $error : $ok; +} + +/** + * Output a task line into a perday intput mode + * + * @param string $inc Line output identificator (start to 0, then increased by recursive call) + * @param int $firstdaytoshow First day to show + * @param int $lastdaytoshow Last day to show + * @param User|null $fuser Restrict list to user if defined + * @param string $parent ID of parent task to show (0 to show all) + * @param Task[] $lines Array of lines (list of tasks, but we will show only if we have a specific role on task) + * @param int $level Level (start to 0, then increased/decrease by recursive call) + * @param string $projectsrole Array of roles user has on project + * @param string $tasksrole Array of roles user has on task + * @param string $mine Show only task lines I am assigned to + * @param int $restricteditformytask 0=No restriction, 1=Enable add time only if task is assigned to me, 2=Enable add time only if tasks is assigned to me and hide others + * @param array $isavailable Array with data that say if user is available for several days for morning and afternoon + * @param int $oldprojectforbreak Old project id of last project break + * @param array $arrayfields Array of additional column + * @param Extrafields $extrafields Object extrafields + * @return array Array with time spent for $fuser for each day of week on tasks in $lines and substasks + */ +function projectLinesPerDayOnMonth(&$inc, $firstdaytoshow, $lastdaytoshow, $fuser, $parent, $lines, &$level, &$projectsrole, &$tasksrole, $mine, $restricteditformytask, &$isavailable, $oldprojectforbreak = 0, $arrayfields = array(), $extrafields = null, $dayInMonth, $noprint = 0) +{ + global $conf, $db, $user, $langs; + + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; + + $form = new Form($db); + $formother = new FormOther($db); + $projectstatic = new Project($db); + $taskstatic = new Task($db); + $thirdpartystatic = new Societe($db); + + $numlines = count($lines); + + $lastprojectid = 0; + $workloadforid = array(); + $totalforeachday = array(); + $lineswithoutlevel0 = array(); + + // Create a smaller array with sublevels only to be used later. This increase dramatically performances. + if ($parent == 0) { // Always and only if at first level + for ($i = 0; $i < $numlines; $i++) { + if ($lines[$i]->fk_task_parent) { + $lineswithoutlevel0[] = $lines[$i]; + } + } + } + + //dol_syslog('projectLinesPerWeek inc='.$inc.' firstdaytoshow='.$firstdaytoshow.' task parent id='.$parent.' level='.$level." count(lines)=".$numlines." count(lineswithoutlevel0)=".count($lineswithoutlevel0)); + + if (empty($oldprojectforbreak)) { + $oldprojectforbreak = (empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT) ? 0 : -1); // 0 = start break, -1 = never break + } + + $restrictBefore = null; + + if (! empty($conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS)) { + require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; + $restrictBefore = dol_time_plus_duree(dol_now(), - $conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS, 'm'); + } + + for ($i = 0; $i < $numlines; $i++) { + if ($parent == 0) { + $level = 0; + } + + if ($lines[$i]->fk_task_parent == $parent) { + $obj = &$lines[$i]; // To display extrafields + + // If we want all or we have a role on task, we show it + if (empty($mine) || !empty($tasksrole[$lines[$i]->id])) { + //dol_syslog("projectLinesPerWeek Found line ".$i.", a qualified task (i have role or want to show all tasks) with id=".$lines[$i]->id." project id=".$lines[$i]->fk_project); + + if ($restricteditformytask == 2 && empty($tasksrole[$lines[$i]->id])) { // we have no role on task and we request to hide such cases + continue; + } + + // Break on a new project + if ($parent == 0 && $lines[$i]->fk_project != $lastprojectid) { + $lastprojectid = $lines[$i]->fk_project; + $projectstatic->id = $lines[$i]->fk_project; + } + + + //var_dump('--- '.$level.' '.$firstdaytoshow.' '.$fuser->id.' '.$projectstatic->id.' '.$workloadforid[$projectstatic->id]); + //var_dump($projectstatic->monthWorkLoadPerTask); + if (empty($workloadforid[$projectstatic->id])) { + loadTimeSpentMonthByDay($firstdaytoshow, $lastdaytoshow, 0, $fuser->id, $projectstatic); // Load time spent from table projet_task_time for the project into this->weekWorkLoad and this->monthWorkLoadPerTask for all days of a week + $workloadforid[$projectstatic->id] = 1; + } + //var_dump('--- '.$projectstatic->id.' '.$workloadforid[$projectstatic->id]); + + $projectstatic->id = $lines[$i]->fk_project; + $projectstatic->ref = $lines[$i]->projectref; + $projectstatic->title = $lines[$i]->projectlabel; + $projectstatic->public = $lines[$i]->public; + $projectstatic->thirdparty_name = $lines[$i]->thirdparty_name; + $projectstatic->status = $lines[$i]->projectstatus; + + $taskstatic->id = $lines[$i]->id; + $taskstatic->ref = ($lines[$i]->ref ? $lines[$i]->ref : $lines[$i]->id); + $taskstatic->label = $lines[$i]->label; + $taskstatic->date_start = $lines[$i]->date_start; + $taskstatic->date_end = $lines[$i]->date_end; + + $thirdpartystatic->id = $lines[$i]->thirdparty_id; + $thirdpartystatic->name = $lines[$i]->thirdparty_name; + $thirdpartystatic->email = $lines[$i]->thirdparty_email; + + if (empty($oldprojectforbreak) || ($oldprojectforbreak != -1 && $oldprojectforbreak != $projectstatic->id)) { + $addcolspan = 0; + if (!empty($arrayfields['t.planned_workload']['checked'])) { + $addcolspan++; + } + if (!empty($arrayfields['t.progress']['checked'])) { + $addcolspan++; + } + if (!empty($arrayfields['timeconsumed']['checked'])) { + $addcolspan++; + } + foreach ($arrayfields as $key => $val) { + if ($val['checked'] && substr($key, 0, 5) == 'efpt.') { + $addcolspan++; + } + } + + if ($conf->global->DOLISIRH_SHOW_ONLY_FAVORITE_TASKS) { + $taskfavorite = isTaskFavorite($lines[$i]->id, $fuser->id); + } else { + $taskfavorite = 1; + } + + if (!$noprint) { + print '' . "\n"; + print ''; + print $projectstatic->getNomUrl(1, '', 0, '' . $langs->transnoentitiesnoconv("YourRole") . ': ' . $projectsrole[$lines[$i]->fk_project]); + if ($thirdpartystatic->id > 0) { + print ' - ' . $thirdpartystatic->getNomUrl(1); + } + if ($projectstatic->title) { + print ' - '; + print '' . dol_trunc($projectstatic->title, '64') . ''; + } + } + + /*$colspan=5+(empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)?0:2); + print ''; + + print ''; + + // PROJECT fields + if (! empty($arrayfields['p.fk_opp_status']['checked'])) print_liste_field_titre($arrayfields['p.fk_opp_status']['label'], $_SERVER["PHP_SELF"], 'p.fk_opp_status', "", $param, '', $sortfield, $sortorder, 'center '); + if (! empty($arrayfields['p.opp_amount']['checked'])) print_liste_field_titre($arrayfields['p.opp_amount']['label'], $_SERVER["PHP_SELF"], 'p.opp_amount', "", $param, '', $sortfield, $sortorder, 'right '); + if (! empty($arrayfields['p.opp_percent']['checked'])) print_liste_field_titre($arrayfields['p.opp_percent']['label'], $_SERVER["PHP_SELF"], 'p.opp_percent', "", $param, '', $sortfield, $sortorder, 'right '); + if (! empty($arrayfields['p.budget_amount']['checked'])) print_liste_field_titre($arrayfields['p.budget_amount']['label'], $_SERVER["PHP_SELF"], 'p.budget_amount', "", $param, '', $sortfield, $sortorder, 'right '); + if (! empty($arrayfields['p.usage_bill_time']['checked'])) print_liste_field_titre($arrayfields['p.usage_bill_time']['label'], $_SERVER["PHP_SELF"], 'p.usage_bill_time', "", $param, '', $sortfield, $sortorder, 'right '); + + $extrafieldsobjectkey='projet'; + $extrafieldsobjectprefix='efp.'; + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; + + print ''; + print ''; + + // PROJECT fields + if (! empty($arrayfields['p.fk_opp_status']['checked'])) + { + print '\n"; + } + if (! empty($arrayfields['p.opp_amount']['checked'])) + { + print '\n"; + } + if (! empty($arrayfields['p.opp_percent']['checked'])) + { + print '\n"; + } + if (! empty($arrayfields['p.budget_amount']['checked'])) + { + print '\n"; + } + if (! empty($arrayfields['p.usage_bill_time']['checked'])) + { + print '\n"; + } + + $extrafieldsobjectkey='projet'; + $extrafieldsobjectprefix='efp.'; + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + + print ''; + print '
'; + $code = dol_getIdFromCode($db, $lines[$i]->fk_opp_status, 'c_lead_status', 'rowid', 'code'); + if ($code) print $langs->trans("OppStatus".$code); + print "'; + print price($lines[$i]->opp_amount, 0, $langs, 1, 0, -1, $conf->currency); + print "'; + print price($lines[$i]->opp_percent, 0, $langs, 1, 0).' %'; + print "'; + print price($lines[$i]->budget_amount, 0, $langs, 1, 0, 0, $conf->currency); + print "'; + print yn($lines[$i]->usage_bill_time); + print "
'; + */ + if (!$noprint) { + print ''; + print ''; + } + } + + if ($oldprojectforbreak != -1) { + $oldprojectforbreak = $projectstatic->id; + } + + if ($conf->global->DOLISIRH_SHOW_ONLY_FAVORITE_TASKS) { + $taskfavorite = isTaskFavorite($lines[$i]->id, $fuser->id); + } else { + $taskfavorite = 1; + } + + if (!$noprint) { + print '' . "\n"; + } + + if (!$noprint) { + // User + /* + print ''; + print $fuser->getNomUrl(1, 'withproject', 'time'); + print ''; + */ + + // Project + if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) { + print ''; + if ($oldprojectforbreak == -1) { + print $projectstatic->getNomUrl(1, '', 0, $langs->transnoentitiesnoconv("YourRole") . ': ' . $projectsrole[$lines[$i]->fk_project]); + } + print ""; + } + + // Thirdparty + if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) { + print ''; + if ($thirdpartystatic->id > 0) { + print $thirdpartystatic->getNomUrl(1, 'project'); + } + print ''; + } + + // Ref + print ''; + print ''; + for ($k = 0; $k < $level; $k++) { + print '
'; + } + print $taskstatic->getNomUrl(1, 'withproject', 'time'); + // Label task + print '
'; + print '' . dol_trunc($taskstatic->label, '64') . ''; + for ($k = 0; $k < $level; $k++) { + print "
"; + } + print "\n"; + + // TASK extrafields + $extrafieldsobjectkey = 'projet_task'; + $extrafieldsobjectprefix = 'efpt.'; + include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_list_print_fields.tpl.php'; + + // Planned Workload + if (!empty($arrayfields['t.planned_workload']['checked'])) { + print ''; + if ($lines[$i]->planned_workload) { + print convertSecondToTime($lines[$i]->planned_workload, 'allhourmin'); + } else { + print '--:--'; + } + print ''; + } + + if (!empty($arrayfields['t.progress']['checked'])) { + // Progress declared % + print ''; + print $formother->select_percent($lines[$i]->progress, $lines[$i]->id . 'progress'); + print ''; + } + + if (!empty($arrayfields['timeconsumed']['checked'])) { + // Time spent by user + print ''; + $firstday = dol_print_date($firstdaytoshow, 'dayrfc'); + $lastday = dol_print_date($lastdaytoshow, 'dayrfc'); +// $currentMonth = date('m', dol_now()); +// $year = GETPOST('reyear', 'int') ? GETPOST('reyear', 'int') : (GETPOST("year", 'int') ? GETPOST("year", "int") : date("Y")); +// $month = GETPOST('remonth', 'int') ? GETPOST('remonth', 'int') : (GETPOST("month", 'int') ? GETPOST("month", "int") : date("m")); +// if ($currentMonth == $month) { +// $lastday = dol_print_date(dol_now(), 'dayrfc'); +// } else { +// $lastdaytoshow = dol_get_last_day($year, $month); +// $lastday = dol_print_date($lastdaytoshow, 'dayrfc'); +// } + $filter = ' AND t.task_datehour BETWEEN ' . "'" . $firstday . "'" . ' AND ' . "'" . $lastday . "'"; + $tmptimespent = $taskstatic->getSummaryOfTimeSpent($fuser->id, $filter); + if ($tmptimespent['total_duration']) { + print convertSecondToTime($tmptimespent['total_duration'], 'allhourmin'); + } else { + print '--:--'; + } + print "\n"; + } + } + + $disabledproject = 1; + $disabledtask = 1; + //print "x".$lines[$i]->fk_project; + //var_dump($lines[$i]); + //var_dump($projectsrole[$lines[$i]->fk_project]); + // If at least one role for project + if ($lines[$i]->public || !empty($projectsrole[$lines[$i]->fk_project]) || $user->rights->projet->all->creer) { + $disabledproject = 0; + $disabledtask = 0; + } + // If $restricteditformytask is on and I have no role on task, i disable edit + if ($restricteditformytask && empty($tasksrole[$lines[$i]->id])) { + $disabledtask = 1; + } + + //var_dump($projectstatic->monthWorkLoadPerTask); + + // Fields to show current time + $tableCell = ''; + $modeinput = 'hours'; + $dayInMonth = num_between_day($firstdaytoshow, $lastdaytoshow, 1); + for ($idw = 0; $idw < $dayInMonth; $idw++) { + $tmpday = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + + $cssonholiday = ''; + if (!$isavailable[$tmpday]['morning'] && !$isavailable[$tmpday]['afternoon']) { + $cssonholiday .= 'onholidayallday '; + } elseif (!$isavailable[$tmpday]['morning']) { + $cssonholiday .= 'onholidaymorning '; + } elseif (!$isavailable[$tmpday]['afternoon']) { + $cssonholiday .= 'onholidayafternoon '; + } + + $tmparray = dol_getdate($tmpday); + $dayWorkLoad = $projectstatic->monthWorkLoadPerTask[$tmpday][$lines[$i]->id]; + $totalforeachday[$tmpday] += $dayWorkLoad; + + $alreadyspent = ''; + if ($dayWorkLoad > 0) { + $alreadyspent = convertSecondToTime($dayWorkLoad, 'allhourmin'); + } + $alttitle = $langs->trans("AddHereTimeSpentForDay", $tmparray['day'], $tmparray['mon']); + + global $numstartworkingday, $numendworkingday; + $cssweekend = ''; + if (($idw + 1 < $numstartworkingday) || ($idw + 1 > $numendworkingday)) { // This is a day is not inside the setup of working days, so we use a week-end css. + //$cssweekend = 'weekend'; + } + + $disabledtaskday = $disabledtask; + + if (! $disabledtask && $restrictBefore && $tmpday < $restrictBefore) { + $disabledtaskday = 1; + } + + $tableCell = ''; + //$tableCell .= 'idw='.$idw.' '.$conf->global->MAIN_START_WEEK.' '.$numstartworkingday.'-'.$numendworkingday; + $placeholder = ''; + if ($alreadyspent) { + $tableCell .= ''; + //$placeholder=' placeholder="00:00"'; + //$tableCell.='+'; + } + $tableCell .= ''; + $tableCell .= ''; + if (!$noprint) { + print $tableCell; + } + } + + if (!$noprint) { + // Warning + print ''; + if ((!$lines[$i]->public) && $disabledproject) { + print $form->textwithpicto('', $langs->trans("UserIsNotContactOfProject")); + } elseif ($disabledtask) { + $titleassigntask = $langs->trans("AssignTaskToMe"); + if ($fuser->id != $user->id) { + $titleassigntask = $langs->trans("AssignTaskToUser", '...'); + } + + print $form->textwithpicto('', $langs->trans("TaskIsNotAssignedToUser", $titleassigntask)); + } + print ''; + + print "\n"; + } + } + + // Call to show task with a lower level (task under the current task) + $inc++; + $level++; + if ($lines[$i]->id > 0) { + //var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level); + //var_dump($totalforeachday); + $ret = projectLinesPerDayOnMonth($inc, $firstdaytoshow, $lastdaytoshow, $fuser, $lines[$i]->id, ($parent == 0 ? $lineswithoutlevel0 : $lines), $level, $projectsrole, $tasksrole, $mine, $restricteditformytask, $isavailable, $oldprojectforbreak, $arrayfields, $extrafields, $dayInMonth, $noprint); + //var_dump('ret with parent='.$lines[$i]->id.' level='.$level); + //var_dump($ret); + foreach ($ret as $key => $val) { + $totalforeachday[$key] += $val; + } + //var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level.' + subtasks'); + //var_dump($totalforeachday); + } + $level--; + } else { + //$level--; + } + } + + return $totalforeachday; +} + +/** + * Load time spent into this->weekWorkLoad and this->weekWorkLoadPerTask for all day of a week of project. + * Note: array weekWorkLoad and weekWorkLoadPerTask are reset and filled at each call. + * + * @param int $datestart First day + * @param int $dateend Last day + * @param int $taskid Filter on a task id + * @param int $userid Time spent by a particular user + * @return int 0 < if OK, >0 if KO + * @throws Exception + */ +function loadTimeSpentMonthByDay($datestart, $dateend, $taskid = 0, $userid = 0, $project) +{ + $error = 0; + + $project->monthWorkLoad = array(); + $project->monthWorkLoadPerTask = array(); + + if (empty($datestart)) { + dol_print_error('', 'Error datestart parameter is empty'); + } + + $sql = "SELECT ptt.rowid as taskid, ptt.task_duration, ptt.task_date, ptt.task_datehour, ptt.fk_task"; + $sql .= " FROM ".MAIN_DB_PREFIX."projet_task_time AS ptt, ".MAIN_DB_PREFIX."projet_task as pt"; + $sql .= " WHERE ptt.fk_task = pt.rowid"; + $sql .= " AND pt.fk_projet = ".((int) $project->id); + $sql .= " AND (ptt.task_date >= '".$project->db->idate($datestart)."' "; + $sql .= " AND ptt.task_date <= '".$project->db->idate($dateend)."')"; + if ($task_id) { + $sql .= " AND ptt.fk_task=".((int) $taskid); + } + if (is_numeric($userid)) { + $sql .= " AND ptt.fk_user=".((int) $userid); + } + + //print $sql; + $resql = $project->db->query($sql); + if ($resql) { + $daylareadyfound = array(); + + $num = $project->db->num_rows($resql); + $i = 0; + // Loop on each record found, so each couple (project id, task id) + while ($i < $num) { + $obj = $project->db->fetch_object($resql); + $day = $project->db->jdate($obj->task_date); // task_date is date without hours + if (empty($daylareadyfound[$day])) { + $project->monthWorkLoad[$day] = $obj->task_duration; + $project->monthWorkLoadPerTask[$day][$obj->fk_task] = $obj->task_duration; + } else { + $project->monthWorkLoad[$day] += $obj->task_duration; + $project->monthWorkLoadPerTask[$day][$obj->fk_task] += $obj->task_duration; + } + $daylareadyfound[$day] = 1; + $i++; + } + $project->db->free($resql); + return 1; + } else { + $project->error = "Error ".$project->db->lasterror(); + dol_syslog(get_class($project)."::fetch ".$project->error, LOG_ERR); + return -1; + } +} + +/** + * Output a task line into a perday intput mode + * + * @param string $inc Line output identificator (start to 0, then increased by recursive call) + * @param int $firstdaytoshow First day to show + * @param User|null $fuser Restrict list to user if defined + * @param string $parent Id of parent task to show (0 to show all) + * @param Task[] $lines Array of lines (list of tasks but we will show only if we have a specific role on task) + * @param int $level Level (start to 0, then increased/decrease by recursive call) + * @param string $projectsrole Array of roles user has on project + * @param string $tasksrole Array of roles user has on task + * @param string $mine Show only task lines I am assigned to + * @param int $restricteditformytask 0=No restriction, 1=Enable add time only if task is assigned to me, 2=Enable add time only if tasks is assigned to me and hide others + * @param array $isavailable Array with data that say if user is available for several days for morning and afternoon + * @param int $oldprojectforbreak Old project id of last project break + * @param array $arrayfields Array of additional column + * @param Extrafields $extrafields Object extrafields + * @return array Array with time spent for $fuser for each day of week on tasks in $lines and substasks + */ +function projectLinesPerWeekDoliSIRH(&$inc, $firstdaytoshow, $fuser, $parent, $lines, &$level, &$projectsrole, &$tasksrole, $mine, $restricteditformytask, &$isavailable, $oldprojectforbreak = 0, $arrayfields = array(), $extrafields = null) +{ + global $conf, $db, $user, $langs; + global $form, $formother, $projectstatic, $taskstatic, $thirdpartystatic; + + $numlines = count($lines); + + $lastprojectid = 0; + $workloadforid = array(); + $totalforeachday = array(); + $lineswithoutlevel0 = array(); + + // Create a smaller array with sublevels only to be used later. This increase dramatically performances. + if ($parent == 0) { // Always and only if at first level + for ($i = 0; $i < $numlines; $i++) { + if ($lines[$i]->fk_task_parent) { + $lineswithoutlevel0[] = $lines[$i]; + } + } + } + + //dol_syslog('projectLinesPerWeek inc='.$inc.' firstdaytoshow='.$firstdaytoshow.' task parent id='.$parent.' level='.$level." count(lines)=".$numlines." count(lineswithoutlevel0)=".count($lineswithoutlevel0)); + + if (empty($oldprojectforbreak)) { + $oldprojectforbreak = (empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT) ? 0 : -1); // 0 = start break, -1 = never break + } + + $restrictBefore = null; + + if (! empty($conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS)) { + require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; + $restrictBefore = dol_time_plus_duree(dol_now(), - $conf->global->PROJECT_TIMESHEET_PREVENT_AFTER_MONTHS, 'm'); + } + + for ($i = 0; $i < $numlines; $i++) { + if ($parent == 0) { + $level = 0; + } + + if ($lines[$i]->fk_task_parent == $parent) { + $obj = &$lines[$i]; // To display extrafields + + // If we want all or we have a role on task, we show it + if (empty($mine) || !empty($tasksrole[$lines[$i]->id])) { + //dol_syslog("projectLinesPerWeek Found line ".$i.", a qualified task (i have role or want to show all tasks) with id=".$lines[$i]->id." project id=".$lines[$i]->fk_project); + + if ($restricteditformytask == 2 && empty($tasksrole[$lines[$i]->id])) { // we have no role on task and we request to hide such cases + continue; + } + + // Break on a new project + if ($parent == 0 && $lines[$i]->fk_project != $lastprojectid) { + $lastprojectid = $lines[$i]->fk_project; + $projectstatic->id = $lines[$i]->fk_project; + } + + //var_dump('--- '.$level.' '.$firstdaytoshow.' '.$fuser->id.' '.$projectstatic->id.' '.$workloadforid[$projectstatic->id]); + //var_dump($projectstatic->weekWorkLoadPerTask); + if (empty($workloadforid[$projectstatic->id])) { + $projectstatic->loadTimeSpent($firstdaytoshow, 0, $fuser->id); // Load time spent from table projet_task_time for the project into this->weekWorkLoad and this->weekWorkLoadPerTask for all days of a week + $workloadforid[$projectstatic->id] = 1; + } + //var_dump($projectstatic->weekWorkLoadPerTask); + //var_dump('--- '.$projectstatic->id.' '.$workloadforid[$projectstatic->id]); + + $projectstatic->id = $lines[$i]->fk_project; + $projectstatic->ref = $lines[$i]->projectref; + $projectstatic->title = $lines[$i]->projectlabel; + $projectstatic->public = $lines[$i]->public; + $projectstatic->thirdparty_name = $lines[$i]->thirdparty_name; + $projectstatic->status = $lines[$i]->projectstatus; + + $taskstatic->id = $lines[$i]->id; + $taskstatic->ref = ($lines[$i]->ref ? $lines[$i]->ref : $lines[$i]->id); + $taskstatic->label = $lines[$i]->label; + $taskstatic->date_start = $lines[$i]->date_start; + $taskstatic->date_end = $lines[$i]->date_end; + + $thirdpartystatic->id = $lines[$i]->thirdparty_id; + $thirdpartystatic->name = $lines[$i]->thirdparty_name; + $thirdpartystatic->email = $lines[$i]->thirdparty_email; + + if (empty($oldprojectforbreak) || ($oldprojectforbreak != -1 && $oldprojectforbreak != $projectstatic->id)) { + $addcolspan = 0; + if (!empty($arrayfields['t.planned_workload']['checked'])) { + $addcolspan++; + } + if (!empty($arrayfields['t.progress']['checked'])) { + $addcolspan++; + } + foreach ($arrayfields as $key => $val) { + if ($val['checked'] && substr($key, 0, 5) == 'efpt.') { + $addcolspan++; + } + } + + if ($conf->global->DOLISIRH_SHOW_ONLY_FAVORITE_TASKS) { + $taskfavorite = isTaskFavorite($lines[$i]->id, $fuser->id); + } else { + $taskfavorite = 1; + } + + print ''."\n"; + print ''; + print $projectstatic->getNomUrl(1, '', 0, ''.$langs->transnoentitiesnoconv("YourRole").': '.$projectsrole[$lines[$i]->fk_project]); + if ($thirdpartystatic->id > 0) { + print ' - '.$thirdpartystatic->getNomUrl(1); + } + if ($projectstatic->title) { + print ' - '; + print ''.dol_trunc($projectstatic->title, '64').''; + } + + /*$colspan=5+(empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)?0:2); + print ''; + + print ''; + + // PROJECT fields + if (! empty($arrayfields['p.fk_opp_status']['checked'])) print_liste_field_titre($arrayfields['p.fk_opp_status']['label'], $_SERVER["PHP_SELF"], 'p.fk_opp_status', "", $param, '', $sortfield, $sortorder, 'center '); + if (! empty($arrayfields['p.opp_amount']['checked'])) print_liste_field_titre($arrayfields['p.opp_amount']['label'], $_SERVER["PHP_SELF"], 'p.opp_amount', "", $param, '', $sortfield, $sortorder, 'right '); + if (! empty($arrayfields['p.opp_percent']['checked'])) print_liste_field_titre($arrayfields['p.opp_percent']['label'], $_SERVER["PHP_SELF"], 'p.opp_percent', "", $param, '', $sortfield, $sortorder, 'right '); + if (! empty($arrayfields['p.budget_amount']['checked'])) print_liste_field_titre($arrayfields['p.budget_amount']['label'], $_SERVER["PHP_SELF"], 'p.budget_amount', "", $param, '', $sortfield, $sortorder, 'right '); + if (! empty($arrayfields['p.usage_bill_time']['checked'])) print_liste_field_titre($arrayfields['p.usage_bill_time']['label'], $_SERVER["PHP_SELF"], 'p.usage_bill_time', "", $param, '', $sortfield, $sortorder, 'right '); + + $extrafieldsobjectkey='projet'; + $extrafieldsobjectprefix='efp.'; + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; + + print ''; + print ''; + + // PROJECT fields + if (! empty($arrayfields['p.fk_opp_status']['checked'])) + { + print '\n"; + } + if (! empty($arrayfields['p.opp_amount']['checked'])) + { + print '\n"; + } + if (! empty($arrayfields['p.opp_percent']['checked'])) + { + print '\n"; + } + if (! empty($arrayfields['p.budget_amount']['checked'])) + { + print '\n"; + } + if (! empty($arrayfields['p.usage_bill_time']['checked'])) + { + print '\n"; + } + + $extrafieldsobjectkey='projet'; + $extrafieldsobjectprefix='efp.'; + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + + print ''; + print '
'; + $code = dol_getIdFromCode($db, $lines[$i]->fk_opp_status, 'c_lead_status', 'rowid', 'code'); + if ($code) print $langs->trans("OppStatus".$code); + print "'; + print price($lines[$i]->opp_amount, 0, $langs, 1, 0, -1, $conf->currency); + print "'; + print price($lines[$i]->opp_percent, 0, $langs, 1, 0).' %'; + print "'; + print price($lines[$i]->budget_amount, 0, $langs, 1, 0, 0, $conf->currency); + print "'; + print yn($lines[$i]->usage_bill_time); + print "
'; + */ + + print ''; + print ''; + } + + if ($oldprojectforbreak != -1) { + $oldprojectforbreak = $projectstatic->id; + } + + if ($conf->global->DOLISIRH_SHOW_ONLY_FAVORITE_TASKS) { + $taskfavorite = isTaskFavorite($lines[$i]->id, $fuser->id); + } else { + $taskfavorite = 1; + } + + print ''."\n"; + + // User + /* + print ''; + print $fuser->getNomUrl(1, 'withproject', 'time'); + print ''; + */ + + // Project + if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) { + print ''; + if ($oldprojectforbreak == -1) { + print $projectstatic->getNomUrl(1, '', 0, $langs->transnoentitiesnoconv("YourRole").': '.$projectsrole[$lines[$i]->fk_project]); + } + print ""; + } + + // Thirdparty + if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) { + print ''; + if ($thirdpartystatic->id > 0) { + print $thirdpartystatic->getNomUrl(1, 'project'); + } + print ''; + } + + // Ref + print ''; + print ''; + for ($k = 0; $k < $level; $k++) { + print '
'; + } + print $taskstatic->getNomUrl(1, 'withproject', 'time'); + // Label task + print '
'; + print ''.dol_trunc($taskstatic->label, '64').''; + for ($k = 0; $k < $level; $k++) { + print "
"; + } + print "\n"; + + // TASK extrafields + $extrafieldsobjectkey = 'projet_task'; + $extrafieldsobjectprefix = 'efpt.'; + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + + // Planned Workload + if (!empty($arrayfields['t.planned_workload']['checked'])) { + print ''; + if ($lines[$i]->planned_workload) { + print convertSecondToTime($lines[$i]->planned_workload, 'allhourmin'); + } else { + print '--:--'; + } + print ''; + } + + if (!empty($arrayfields['t.progress']['checked'])) { + // Progress declared % + print ''; + print $formother->select_percent($lines[$i]->progress, $lines[$i]->id.'progress'); + print ''; + } + + if (!empty($arrayfields['timeconsumed']['checked'])) { + // Time spent by everybody + print ''; + // $lines[$i]->duration is a denormalised field = summ of time spent by everybody for task. What we need is time consummed by user + if ($lines[$i]->duration) { + print ''; + print convertSecondToTime($lines[$i]->duration, 'allhourmin'); + print ''; + } else { + print '--:--'; + } + print "\n"; + + // Time spent by user + print ''; + $firstday = dol_print_date($firstdaytoshow, 'dayrfc'); + $CurrentDate = dol_getdate(dol_now()); + $currentWeek = getWeekNumber($CurrentDate['mday'], $CurrentDate['mon'], $CurrentDate['year']); + $Date = dol_getdate($firstdaytoshow); + $Week = getWeekNumber($Date['mday'], $Date['mon'], $Date['year']); + + if ($currentWeek == $Week) { + $firstDay = date( 'd', $firstdaytoshow); + $currentDay = date( 'd', dol_now()); + $nbday = $currentDay - $firstDay; + } else { + $nbday = 6; + } + $lastdaytoshow = dol_time_plus_duree($firstdaytoshow, $nbday, 'd'); + + $lastday = dol_print_date($lastdaytoshow, 'dayrfc'); + $filter = ' AND t.task_datehour BETWEEN ' . "'" . $firstday . "'" . ' AND ' . "'" . $lastday . "'"; + $tmptimespent = $taskstatic->getSummaryOfTimeSpent($fuser->id, $filter); + if ($tmptimespent['total_duration']) { + print convertSecondToTime($tmptimespent['total_duration'], 'allhourmin'); + } else { + print '--:--'; + } + print "\n"; + } + + $disabledproject = 1; + $disabledtask = 1; + //print "x".$lines[$i]->fk_project; + //var_dump($lines[$i]); + //var_dump($projectsrole[$lines[$i]->fk_project]); + // If at least one role for project + if ($lines[$i]->public || !empty($projectsrole[$lines[$i]->fk_project]) || $user->rights->projet->all->creer) { + $disabledproject = 0; + $disabledtask = 0; + } + // If $restricteditformytask is on and I have no role on task, i disable edit + if ($restricteditformytask && empty($tasksrole[$lines[$i]->id])) { + $disabledtask = 1; + } + + //var_dump($projectstatic->weekWorkLoadPerTask); + + // Fields to show current time + $tableCell = ''; + $modeinput = 'hours'; + for ($idw = 0; $idw < 7; $idw++) { + $tmpday = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + + $cssonholiday = ''; + if (!$isavailable[$tmpday]['morning'] && !$isavailable[$tmpday]['afternoon']) { + $cssonholiday .= 'onholidayallday '; + } elseif (!$isavailable[$tmpday]['morning']) { + $cssonholiday .= 'onholidaymorning '; + } elseif (!$isavailable[$tmpday]['afternoon']) { + $cssonholiday .= 'onholidayafternoon '; + } + + $tmparray = dol_getdate($tmpday); + $dayWorkLoad = $projectstatic->weekWorkLoadPerTask[$tmpday][$lines[$i]->id]; + $totalforeachday[$tmpday] += $dayWorkLoad; + + $alreadyspent = ''; + if ($dayWorkLoad > 0) { + $alreadyspent = convertSecondToTime($dayWorkLoad, 'allhourmin'); + } + $alttitle = $langs->trans("AddHereTimeSpentForDay", $tmparray['day'], $tmparray['mon']); + + global $numstartworkingday, $numendworkingday; + $cssweekend = ''; + if (($idw + 1 < $numstartworkingday) || ($idw + 1 > $numendworkingday)) { // This is a day is not inside the setup of working days, so we use a week-end css. + $cssweekend = 'weekend'; + } + + $disabledtaskday = $disabledtask; + + if (! $disabledtask && $restrictBefore && $tmpday < $restrictBefore) { + $disabledtaskday = 1; + } + + $tableCell = ''; + //$tableCell .= 'idw='.$idw.' '.$conf->global->MAIN_START_WEEK.' '.$numstartworkingday.'-'.$numendworkingday; + $placeholder = ''; + if ($alreadyspent) { + $tableCell .= ''; + //$placeholder=' placeholder="00:00"'; + //$tableCell.='+'; + } + $tableCell .= ''; + $tableCell .= ''; + print $tableCell; + } + + // Warning + print ''; + if ((!$lines[$i]->public) && $disabledproject) { + print $form->textwithpicto('', $langs->trans("UserIsNotContactOfProject")); + } elseif ($disabledtask) { + $titleassigntask = $langs->trans("AssignTaskToMe"); + if ($fuser->id != $user->id) { + $titleassigntask = $langs->trans("AssignTaskToUser", '...'); + } + + print $form->textwithpicto('', $langs->trans("TaskIsNotAssignedToUser", $titleassigntask)); + } + print ''; + + print "\n"; + } + + // Call to show task with a lower level (task under the current task) + $inc++; + $level++; + if ($lines[$i]->id > 0) { + //var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level); + //var_dump($totalforeachday); + $ret = projectLinesPerWeekDoliSIRH($inc, $firstdaytoshow, $fuser, $lines[$i]->id, ($parent == 0 ? $lineswithoutlevel0 : $lines), $level, $projectsrole, $tasksrole, $mine, $restricteditformytask, $isavailable, $oldprojectforbreak, $arrayfields, $extrafields); + //var_dump('ret with parent='.$lines[$i]->id.' level='.$level); + //var_dump($ret); + foreach ($ret as $key => $val) { + $totalforeachday[$key] += $val; + } + //var_dump('totalforeachday after taskid='.$lines[$i]->id.' and previous one on level '.$level.' + subtasks'); + //var_dump($totalforeachday); + } + $level--; + } else { + //$level--; + } + } + + return $totalforeachday; +} + +/** + * Return a string to show the box with list of available documents for object. + * This also set the property $this->numoffiles + * + * @param string $modulepart Module the files are related to ('propal', 'facture', 'facture_fourn', 'mymodule', 'mymodule:nameofsubmodule', 'mymodule_temp', ...) + * @param string $modulesubdir Existing (so sanitized) sub-directory to scan (Example: '0/1/10', 'FA/DD/MM/YY/9999'). Use '' if file is not into subdir of module. + * @param string $filedir Directory to scan + * @param string $urlsource Url of origin page (for return) + * @param int|string[] $genallowed Generation is allowed (1/0 or array list of templates) + * @param int $delallowed Remove is allowed (1/0) + * @param string $modelselected Model to preselect by default + * @param integer $allowgenifempty Allow generation even if list of template ($genallowed) is empty (show however a warning) + * @param integer $forcenomultilang Do not show language option (even if MAIN_MULTILANGS defined) + * @param int $iconPDF Deprecated, see getDocumentsLink + * @param int $notused Not used + * @param integer $noform Do not output html form tags + * @param string $param More param on http links + * @param string $title Title to show on top of form. Example: '' (Default to "Documents") or 'none' + * @param string $buttonlabel Label on submit button + * @param string $codelang Default language code to use on lang combo box if multilang is enabled + * @param string $morepicto Add more HTML content into cell with picto + * @param Object $object Object when method is called from an object card. + * @param int $hideifempty Hide section of generated files if there is no file + * @param string $removeaction (optional) The action to remove a file + * @param int $active (optional) To show gen button disabled + * @param string $tooltiptext (optional) Tooltip text when gen button disabled + * @return string Output string with HTML array of documents (might be empty string) + */ +function dolisirhshowdocuments($modulepart, $modulesubdir, $filedir, $urlsource, $genallowed, $delallowed = 0, $modelselected = '', $allowgenifempty = 1, $forcenomultilang = 0, $notused = 0, $noform = 0, $param = '', $title = '', $buttonlabel = '', $codelang = '', $morepicto = '', $object = null, $hideifempty = 0, $removeaction = 'remove_file', $active = 1, $tooltiptext = '') +{ + global $db, $langs, $conf, $user, $hookmanager, $form; + + if ( ! is_object($form)) $form = new Form($db); + + include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php'; + + // Add entity in $param if not already exists + if ( ! preg_match('/entity\=[0-9]+/', $param)) { + $param .= ($param ? '&' : '') . 'entity=' . ( ! empty($object->entity) ? $object->entity : $conf->entity); + } + + $hookmanager->initHooks(array('formfile')); + + // Get list of files + $file_list = null; + if ( ! empty($filedir)) { + $file_list = dol_dir_list($filedir, 'files', 0, '(\.odt|\.zip|\.pdf)', '', 'date', SORT_DESC, 1); + } + if ($hideifempty && empty($file_list)) return ''; + + $out = ''; + $forname = 'builddoc'; + $headershown = 0; + $showempty = 0; + + $out .= "\n" . '' . "\n"; + + $titletoshow = $langs->trans("Documents"); + if ( ! empty($title)) $titletoshow = ($title == 'none' ? '' : $title); + + // Show table + if ($genallowed) { + $submodulepart = $modulepart; + // modulepart = 'nameofmodule' or 'nameofmodule:NameOfObject' + $tmp = explode(':', $modulepart); + if ( ! empty($tmp[1])) { + $modulepart = $tmp[0]; + $submodulepart = $tmp[1]; + } + + // For normalized external modules. + $file = dol_buildpath('/' . $modulepart . '/core/modules/' . $modulepart . '/' . strtolower($submodulepart) . '/modules_' . strtolower($submodulepart) . '.php', 0); + include_once $file; + + $class = 'ModeleODT' . $submodulepart; + + if (class_exists($class)) { + if (preg_match('/specimen/', $param)) { + $type = strtolower($class) . 'specimen'; + $modellist = array(); + + include_once DOL_DOCUMENT_ROOT . '/core/lib/functions2.lib.php'; + $modellist = getListOfModels($db, $type, 0); + } else { + $modellist = call_user_func($class . '::liste_modeles', $db, 100); + } + } else { + dol_print_error($db, "Bad value for modulepart '" . $modulepart . "' in showdocuments"); + return -1; + } + + // Set headershown to avoid to have table opened a second time later + $headershown = 1; + + if (empty($buttonlabel)) $buttonlabel = $langs->trans('Generate'); + + if ($conf->browser->layout == 'phone') $urlsource .= '#' . $forname . '_form'; // So we switch to form after a generation + if (empty($noform)) $out .= '
'; + $out .= ''; + $out .= ''; + + $out .= load_fiche_titre($titletoshow, '', ''); + $out .= '
'; + $out .= ''; + + $out .= ''; + + $addcolumforpicto = ($delallowed || $morepicto); + $colspan = (3 + ($addcolumforpicto ? 1 : 0)); $colspanmore = 0; + + $out .= ''; + + if ( ! empty($hookmanager->hooks['formfile'])) { + foreach ($hookmanager->hooks['formfile'] as $module) { + if (method_exists($module, 'formBuilddocLineOptions')) { + $colspanmore++; + $out .= ''; + } + } + } + $out .= ''; + + // Execute hooks + $parameters = array('colspan' => ($colspan + $colspanmore), 'socid' => (isset($GLOBALS['socid']) ? $GLOBALS['socid'] : ''), 'id' => (isset($GLOBALS['id']) ? $GLOBALS['id'] : ''), 'modulepart' => $modulepart); + if (is_object($hookmanager)) { + $reshook = $hookmanager->executeHooks('formBuilddocOptions', $parameters, $GLOBALS['object']); + $out .= $hookmanager->resPrint; + } + } + + // Get list of files + if ( ! empty($filedir)) { + $link_list = array(); + if (is_object($object) && $object->id > 0) { + require_once DOL_DOCUMENT_ROOT . '/core/class/link.class.php'; + $link = new Link($db); + $sortfield = $sortorder = null; + $res = $link->fetchAll($link_list, $object->element, $object->id, $sortfield, $sortorder); + } + + $out .= '' . "\n"; + + // Show title of array if not already shown + if (( ! empty($file_list) || ! empty($link_list) || preg_match('/^massfilesarea/', $modulepart)) + && ! $headershown) { + $headershown = 1; + $out .= '
' . $titletoshow . '
' . "\n"; + $out .= '
'; + $out .= '
'; + // Model + if ( ! empty($modellist)) { + asort($modellist); + $out .= ' '; + $modellist = array_filter($modellist, 'remove_indexdolisirh'); + if (is_array($modellist)) { // If there is only one element + foreach ($modellist as $key => $modellistsingle) { + $arrayvalues = preg_replace('/template_/', '', $modellistsingle); + $modellist[$key] = $langs->trans($arrayvalues); + $modelselected = $key; + } + } + $morecss = 'maxwidth200'; + if ($conf->browser->layout == 'phone') $morecss = 'maxwidth100'; + $out .= $form->selectarray('model', $modellist, $modelselected, $showempty, 0, 0, '', 0, 0, 0, '', $morecss); + + if ($conf->use_javascript_ajax) { + $out .= ajax_combobox('model'); + } + } else { + $out .= '
' . $langs->trans("Files") . '
'; + } + + // Button + if ($active) { + $genbutton = ''; + $genbutton .= ''; + } else { + $genbutton = ''; + $genbutton .= ''; + } + +// if ( ! $allowgenifempty && ! is_array($modellist) && empty($modellist)) $genbutton .= ' disabled'; +// $genbutton .= '>'; +// if ($allowgenifempty && ! is_array($modellist) && empty($modellist) && empty($conf->dol_no_mouse_hover) && $modulepart != 'unpaid') { +// $langs->load("errors"); +// $genbutton .= ' ' . img_warning($langs->transnoentitiesnoconv("WarningNoDocumentModelActivated")); +// } +// if ( ! $allowgenifempty && ! is_array($modellist) && empty($modellist) && empty($conf->dol_no_mouse_hover) && $modulepart != 'unpaid') $genbutton = ''; +// if (empty($modellist) && ! $showempty && $modulepart != 'unpaid') $genbutton = ''; + $out .= $genbutton; +// if ( ! $active) { +// $htmltooltip = ''; +// $htmltooltip .= $tooltiptext; +// +// $out .= ''; +// $out .= $form->textwithpicto($langs->trans('Help'), $htmltooltip, 1, 0); +// $out .= ''; +// } + + $out .= '
' . "\n"; + } + + // Loop on each file found + if (is_array($file_list)) { + foreach ($file_list as $file) { + // Define relative path for download link (depends on module) + $relativepath = $file["name"]; // Cas general + if ($modulesubdir) $relativepath = $modulesubdir . "/" . $file["name"]; // Cas propal, facture... + + $out .= ''; + + $documenturl = DOL_URL_ROOT . '/document.php'; + if (isset($conf->global->DOL_URL_ROOT_DOCUMENT_PHP)) $documenturl = $conf->global->DOL_URL_ROOT_DOCUMENT_PHP; // To use another wrapper + + // Show file name with link to download + $out .= ''; + + // Show file size + $size = ( ! empty($file['size']) ? $file['size'] : dol_filesize($filedir . "/" . $file["name"])); + $out .= ''; + + // Show file date + $date = ( ! empty($file['date']) ? $file['date'] : dol_filemtime($filedir . "/" . $file["name"])); + $out .= ''; + + if ($delallowed || $morepicto) { + $out .= ''; + } + + if (is_object($hookmanager)) { + $parameters = array('colspan' => ($colspan + $colspanmore), 'socid' => (isset($GLOBALS['socid']) ? $GLOBALS['socid'] : ''), 'id' => (isset($GLOBALS['id']) ? $GLOBALS['id'] : ''), 'modulepart' => $modulepart, 'relativepath' => $relativepath); + $res = $hookmanager->executeHooks('formBuilddocLineOptions', $parameters, $file); + if (empty($res)) { + $out .= $hookmanager->resPrint; // Complete line + $out .= ''; + } else { + $out = $hookmanager->resPrint; // Replace all $out + } + } + } + } + // Loop on each link found + // if (is_array($link_list)) + // { + // $colspan = 2; + // + // foreach ($link_list as $file) + // { + // $out .= ''; + // $out .= ''; + // $out .= ''; + // if ($delallowed || $printer || $morepicto) $out .= ''; + // $out .= ''."\n"; + // } + // } + + if (count($file_list) == 0 && count($link_list) == 0 && $headershown) { + $out .= '' . "\n"; + } + } + + if ($headershown) { + // Affiche pied du tableau + $out .= "
'; + $out .= 'trans("File") . ': ' . $file["name"]); + $out .= dol_trunc($file["name"], 150); + $out .= '' . "\n"; + $out .= '' . dol_print_size($size, 1, 1) . '' . dol_print_date($date, 'dayhour', 'tzuser') . ''; + if ($delallowed) { + $tmpurlsource = preg_replace('/#[a-zA-Z0-9_]*$/', '', $urlsource); + $out .= '' . img_picto($langs->trans("Delete"), 'delete') . ''; + } + if ($morepicto) { + $morepicto = preg_replace('/__FILENAMEURLENCODED__/', urlencode($relativepath), $morepicto); + $out .= $morepicto; + } + $out .= '
'; + // $out .= ''; + // $out .= $file->label; + // $out .= ''; + // $out .= ''; + // $out .= dol_print_date($file->datea, 'dayhour'); + // $out .= '
' . $langs->trans("None") . '
\n"; + $out .= "
\n"; + if ($genallowed) { + if (empty($noform)) $out .= '
' . "\n"; + } + } + $out .= '' . "\n"; + + return $out; +} + +/** + * Exclude index.php files from list of models for document generation + * + * @param string $model + * @return '' or $model + */ +function remove_indexdolisirh($model) +{ + if (preg_match('/index.php/', $model)) { + return ''; + } else { + return $model; + } +} + +/** + * Return list of activated modules usable for document generation + * + * @param DoliDB $db Database handler + * @param string $type Type of models (company, invoice, ...) + * @param int $maxfilenamelength Max length of value to show + * @return array|int 0 if no module is activated, or array(key=>label). For modules that need directory scan, key is completed with ":filename". + */ +function getListOfModelsDoliSIRH($db, $type, $maxfilenamelength = 0) +{ + global $conf, $langs; + $liste = array(); + $found = 0; + $dirtoscan = ''; + + $sql = "SELECT nom as id, nom as doc_template_name, libelle as label, description as description"; + $sql .= " FROM ".MAIN_DB_PREFIX."document_model"; + $sql .= " WHERE type = '".$db->escape($type)."'"; + $sql .= " AND entity IN (0,".$conf->entity.")"; + $sql .= " ORDER BY description DESC"; + + dol_syslog('/core/lib/function2.lib.php::getListOfModels', LOG_DEBUG); + $resql = $db->query($sql); + if ($resql) { + $num = $db->num_rows($resql); + $i = 0; + while ($i < $num) { + $found = 1; + + $obj = $db->fetch_object($resql); + + // If this generation module needs to scan a directory, then description field is filled + // with the constant that contains list of directories to scan (COMPANY_ADDON_PDF_ODT_PATH, ...). + if (!empty($obj->description)) { // A list of directories to scan is defined + include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + + $const = $obj->description; + //irtoscan.=($dirtoscan?',':'').preg_replace('/[\r\n]+/',',',trim($conf->global->$const)); + $dirtoscan = preg_replace('/[\r\n]+/', ',', trim($conf->global->$const)); + + $listoffiles = array(); + + // Now we add models found in directories scanned + $listofdir = explode(',', $dirtoscan); + foreach ($listofdir as $key => $tmpdir) { + $tmpdir = trim($tmpdir); + $tmpdir = preg_replace('/DOL_DATA_ROOT/', DOL_DATA_ROOT, $tmpdir); + $tmpdir = preg_replace('/DOL_DOCUMENT_ROOT/', DOL_DOCUMENT_ROOT, $tmpdir); + + if (!$tmpdir) { + unset($listofdir[$key]); + continue; + } + if (is_dir($tmpdir)) { + // all type of template is allowed + $tmpfiles = dol_dir_list($tmpdir, 'files', 0, '', '', 'name', SORT_ASC, 0); + if (count($tmpfiles)) { + $listoffiles = array_merge($listoffiles, $tmpfiles); + } + } + } + + if (count($listoffiles)) { + foreach ($listoffiles as $record) { + $max = ($maxfilenamelength ? $maxfilenamelength : 28); + $liste[$obj->id.':'.$record['fullname']] = dol_trunc($record['name'], $max, 'middle'); + } + } else { + $liste[0] = $obj->label.': '.$langs->trans("None"); + } + } else { + if ($type == 'member' && $obj->doc_template_name == 'standard') { // Special case, if member template, we add variant per format + global $_Avery_Labels; + include_once DOL_DOCUMENT_ROOT.'/core/lib/format_cards.lib.php'; + foreach ($_Avery_Labels as $key => $val) { + $liste[$obj->id.':'.$key] = ($obj->label ? $obj->label : $obj->doc_template_name).' '.$val['name']; + } + } else { + // Common usage + $liste[$obj->id] = $obj->label ? $obj->label : $obj->doc_template_name; + } + } + $i++; + } + } else { + dol_print_error($db); + return -1; + } + + if ($found) { + return $liste; + } else { + return 0; + } +} + diff --git a/lib/dolisirh_timesheet.lib.php b/lib/dolisirh_timesheet.lib.php new file mode 100644 index 0000000..641b884 --- /dev/null +++ b/lib/dolisirh_timesheet.lib.php @@ -0,0 +1,87 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file lib/dolisirh_timesheet.lib.php + * \ingroup dolisirh + * \brief Library files with common functions for TimeSheet + */ + +/** + * Prepare array of tabs for TimeSheet + * + * @param TimeSheet $object TimeSheet + * @return array Array of tabs + */ +function timesheetPrepareHead(TimeSheet $object): array +{ + global $conf, $langs; + + $langs->load("dolisirh@dolisirh"); + + $h = 0; + $head = array(); + + $head[$h][0] = dol_buildpath("/dolisirh/view/timesheet/timesheet_card.php", 1).'?id='.$object->id; + $head[$h][1] = ' ' . $langs->trans("Card"); + $head[$h][2] = 'card'; + $h++; + + if (isset($object->fields['note_public']) || isset($object->fields['note_private'])) { + $nbNote = 0; + if (!empty($object->note_private)) { + $nbNote++; + } + if (!empty($object->note_public)) { + $nbNote++; + } + $head[$h][0] = dol_buildpath('/dolisirh/view/timesheet/timesheet_note.php', 1).'?id='.$object->id; + $head[$h][1] = ' ' .$langs->trans('Notes'); + if ($nbNote > 0) { + $head[$h][1] .= (empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) ? ''.$nbNote.'' : ''); + } + $head[$h][2] = 'note'; + $h++; + } + +// require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; +// require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php'; +// $upload_dir = $conf->dolisirh->dir_output."/timesheet/".dol_sanitizeFileName($object->ref); +// $nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$')); +// $nbLinks = Link::count($db, $object->element, $object->id); +// $head[$h][0] = dol_buildpath("/dolisirh/view/timesheet/timesheet_document.php", 1).'?id='.$object->id; +// $head[$h][1] = $langs->trans('Documents'); +// if (($nbFiles + $nbLinks) > 0) { +// $head[$h][1] .= ''.($nbFiles + $nbLinks).''; +// } +// $head[$h][2] = 'document'; +// $h++; + + $head[$h][0] = dol_buildpath("/dolisirh/view/timesheet/timesheet_agenda.php", 1).'?id='.$object->id; + $head[$h][1] = ' ' . $langs->trans("Events"); + $head[$h][2] = 'agenda'; + $h++; + + $head[$h][0] = dol_buildpath("/dolisirh/view/timesheet/timesheet_attendants.php", 1) . '?id=' . $object->id; + $head[$h][1] = ' ' . $langs->trans("Attendants"); + $head[$h][2] = 'attendants'; + $h++; + + complete_head_from_modules($conf, $langs, $object, $head, $h, 'timesheet@dolisirh'); + + return $head; +} diff --git a/lib/index.php b/lib/index.php new file mode 100644 index 0000000..17927e6 --- /dev/null +++ b/lib/index.php @@ -0,0 +1,2 @@ +=6.0.0" + } + }, + "node_modules/@types/linkify-it": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", + "integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==", + "dev": true + }, + "node_modules/@types/markdown-it": { + "version": "12.2.3", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", + "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", + "dev": true, + "dependencies": { + "@types/linkify-it": "*", + "@types/mdurl": "*" + } + }, + "node_modules/@types/mdurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", + "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", + "dev": true + }, + "node_modules/ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "dependencies": { + "ansi-wrap": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-cyan": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz", + "integrity": "sha512-eCjan3AVo/SxZ0/MyIYRtkpxIu/H3xZN7URr1vXVrISxeyz8fUFz0FJziamK4sS8I+t35y4rHg1b2PklyBe/7A==", + "dependencies": { + "ansi-wrap": "0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha512-HrgGIZUl8h2EHuZaU9hTR/cU5nhKxpVE1V6kdGsQ8e4zirElJ5fvtfc8N7Q1oq1aatO275i8pUFUCpNWCAnVWw==", + "dependencies": { + "ansi-wrap": "0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-red": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "integrity": "sha512-ewaIr5y+9CUTGFwZfpECUbFlGcC0GCw1oqR9RI6h1gQCd9Aj2GxSckCnPsVJnmfMZbwFYE+leZGASgkWl06Jow==", + "dependencies": { + "ansi-wrap": "0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha512-ZyznvL8k/FZeQHr2T6LzcJ/+vBApDnMNZvfVFy3At0knswWd6rJ3/0Hhmpu8oqa6C92npmozs890sX9Dl6q+Qw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha512-WLbYiXzD3y/ATLZFufV/rZvWdZOs+Z/+5v1rBZ463Jn398pa6kcde27cvozYnBoxXblGZTFfoPpsaEw0orU5BA==", + "dev": true, + "dependencies": { + "buffer-equal": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-filter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", + "integrity": "sha512-A2BETWCqhsecSvCkWAeVBFLH6sXEUGASuzkpjL3GR1SlL/PWL6M3J8EAAld2Uubmh39tvkJTqC9LeLHCUKmFXA==", + "dev": true, + "dependencies": { + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", + "integrity": "sha512-tVqVTHt+Q5Xb09qRkbu+DidW1yYzz5izWS2Xm2yFm7qJnmUfz4HPzNxbHkdRJbz2lrqI7S+z17xNYdFcBBO8Hw==", + "dev": true, + "dependencies": { + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha512-LeZY+DZDRnvP7eMuQ6LHfCzUGxAAIViUBliK24P3hWXL6y4SortgR6Nim6xrkfSLlmH0+k+9NYNwVC2s53ZrYQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-initial": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", + "integrity": "sha512-BC4Yl89vneCYfpLrs5JU2aAu9/a+xWbeKhvISg9PT7eWFB9UlRvI+rKEtk6mgxWr3dSkk9gQ8hCrdqt06NXPdw==", + "dev": true, + "dependencies": { + "array-slice": "^1.0.0", + "is-number": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-initial/node_modules/is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-last": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", + "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", + "dev": true, + "dependencies": { + "is-number": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-last/node_modules/is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-sort": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", + "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", + "dev": true, + "dependencies": { + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "node_modules/async-done": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", + "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^2.0.0", + "stream-exhaust": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "node_modules/async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha512-VPXfB4Vk49z1LHHodrEQ6Xf7W4gg1w0dAPROHngx7qgDjqmIQ+fXmwgGXTW/ITLai0YLSvWepJOP9EVpMnEAcw==", + "dev": true, + "dependencies": { + "async-done": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/autoprefixer": { + "version": "9.8.8", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.8.tgz", + "integrity": "sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==", + "dev": true, + "dependencies": { + "browserslist": "^4.12.0", + "caniuse-lite": "^1.0.30001109", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "picocolors": "^0.2.1", + "postcss": "^7.0.32", + "postcss-value-parser": "^4.1.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + } + }, + "node_modules/bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha512-bZOOfCb3gXBXbTFXq3OZtGR88LwGeJvzu6szttaIzymOTS4ZttBNOWSv7aLZja2EMycKtRYV0Oa8SNKH/zkxvg==", + "dev": true, + "dependencies": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dependencies": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha512-3vqtKL1N45I5dV0RdssXZG7X6pCqQrWPNOlBPZPrd+QkE2HEhR57Z04m0KtpbsZH73j+a3F8UD1TQnn+ExTvIA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/bowser": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-1.9.4.tgz", + "integrity": "sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/browserslist": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", + "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001370", + "electron-to-chromium": "^1.4.202", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.5" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha512-tcBWO2Dl4e7Asr9hTGcpVrCe+F7DubpmqWCTbj4FHLmjqO2hIaC383acQubWtRJhdceqs5uBHs6Es+Sk//RKiQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dependencies": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001378", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001378.tgz", + "integrity": "sha512-JVQnfoO7FK7WvU4ZkBRbPjaot4+YqxogSDosHv0Hv5mWpUESmN+UubMU6L/hGz8QlQ2aY5U0vR6MOs6j/CXpNA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, + "node_modules/catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "dev": true, + "dependencies": { + "lodash": "^4.17.15" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalkline": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/chalkline/-/chalkline-0.0.5.tgz", + "integrity": "sha512-FYfZecaZ6+eG2AVBzKmi5x1WgqRo7491HZ9VfJztMMkGFYQDEh4h4dBUJV1TUbUoix1tWUD/0QDSdu3SW3SXIg==", + "dependencies": { + "ansi-styles": "^2.1.0", + "chalk": "^1.1.1", + "escape-string-regexp": "^1.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chalkline/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chalkline/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chalkline/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chalkline/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chalkline/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "deprecated": "Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "node_modules/class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dependencies": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w==", + "dev": true, + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha512-KLLTJWrvwIP+OPfMn0x2PheDEP20RPUcGXj/ERegTgdmPEZylALQldygiqrPPu8P45uNuPs7ckmReLY6v/iA5g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag==", + "dev": true + }, + "node_modules/cloneable-readable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", + "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/coffeescript": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-2.7.0.tgz", + "integrity": "sha512-hzWp6TUE2d/jCcN67LrW1eh5b/rSDKQK6oD6VMLlggYVUUFexgTH9z3dNYihzX4RMhze5FTUsUmOXViJKFQR/A==", + "dev": true, + "bin": { + "cake": "bin/cake", + "coffee": "bin/coffee" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/collection-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", + "integrity": "sha512-5D2XXSpkOnleOI21TG7p3T0bGAsZ/XknZpKBmGYyluO8pw4zA3K8ZlrBIbC4FXg3m6z/RNFiUFfT2sQK01+UHA==", + "dev": true, + "dependencies": { + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==", + "dependencies": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "node_modules/composer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/composer/-/composer-4.1.0.tgz", + "integrity": "sha512-qIIoNYjwFHrQFUdB8kD3pZs30+JeYK9149EpOYr/NVrii00KMO31IonzZMeRSU4qazyWZpEgVzkBmQ6VFWxedA==", + "dependencies": { + "pretty-time": "^1.1.0", + "use": "^3.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-with-sourcemaps": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", + "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", + "dev": true, + "dependencies": { + "source-map": "^0.6.1" + } + }, + "node_modules/convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/convert-source-map/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/copy-props": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", + "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", + "dev": true, + "dependencies": { + "each-props": "^1.3.2", + "is-plain-object": "^5.0.0" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cycle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "integrity": "sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "node_modules/dateformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha512-GODcnWq3YGoTnygPfi02ygEiRxqUxpJwuRHjdhJYuxpcZmDq4rjBiXYmbCCzStxo176ixfLT6i4NPwQooRySnw==", + "engines": { + "node": "*" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/default-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", + "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", + "dev": true, + "dependencies": { + "kind-of": "^5.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-resolution": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", + "integrity": "sha512-2xaP6GiwVwOEbXCGoJ4ufgC76m8cj805jrghScewJC2ZDsb9U0b4BIrba+xt/Uytyd0HvQ6+WymSRTfnYj59GQ==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==", + "dependencies": { + "clone": "^1.0.2" + } + }, + "node_modules/define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dev": true, + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deprecated": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", + "integrity": "sha512-BRACtc6B1mJe2J2mruHFqHWrtLy0Qppu/7LKdqWH3o/9j1L/1phPUaQV+2S3H8ZDW0k6h+NEOKcHBDRikWLiOA==", + "engines": { + "node": ">= 0.9" + } + }, + "node_modules/detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" + }, + "node_modules/duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha512-+AWBwjGadtksxjOQSFDhPNQbed7icNXApT4+2BNpsXzcCBiInq2H9XW0O8sfHFaPmnQRs7cg/P0fAr2IWQSW0g==", + "dependencies": { + "readable-stream": "~1.1.9" + } + }, + "node_modules/duplexer2/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "node_modules/duplexer2/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/duplexer2/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" + }, + "node_modules/duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/each-props": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", + "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" + } + }, + "node_modules/each-props/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/easy-table": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/easy-table/-/easy-table-1.2.0.tgz", + "integrity": "sha512-OFzVOv03YpvtcWGe5AayU5G2hgybsg3iqA6drU8UaoZyB9jLGMTrz9+asnLp/E+6qPh88yEI1gvyZFZ41dmgww==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "optionalDependencies": { + "wcwidth": "^1.0.1" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.225", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.225.tgz", + "integrity": "sha512-ICHvGaCIQR3P88uK8aRtx8gmejbVJyC6bB4LEC3anzBrIzdzC7aiZHY4iFfXhN4st6I7lMO0x4sgBHf/7kBvRw==", + "dev": true + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es5-ext": { + "version": "0.10.62", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", + "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "node_modules/es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "dependencies": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "dependencies": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha512-AFASGfIlnIbkKPQwX1yHaDjFvh/1gyKJODme52V6IORh69uEYgZp0o9C+qsIGNVEiuuhQU0CSSl++Rlegg1qvA==", + "dev": true, + "dependencies": { + "fill-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-range/node_modules/fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true, + "dependencies": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-range/node_modules/is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha512-QUzH43Gfb9+5yckcrSA0VBDwEtDUchrk4F6tfJZQuNzDJbEDB9cZNzSfXGQ1jqmdDY/kl41lUOWM9syA8z8jlg==", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-range/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", + "dev": true, + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-range/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ext": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", + "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", + "dev": true, + "dependencies": { + "type": "^2.5.0" + } + }, + "node_modules/ext/node_modules/type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==", + "dev": true + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dependencies": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==", + "engines": { + "node": "> 0.1.90" + } + }, + "node_modules/fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "dependencies": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/fast-levenshtein": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", + "integrity": "sha512-Ia0sQNrMPXXkqVFt6w6M1n1oKo3NfKs+mvaV811Jwir7vAk9a6PVV9VPYf6X3BU97QiLEmuW3uXH9u87zDFfdw==", + "dev": true + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "node_modules/filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha512-BTCqyBaWBTsauvnHiE8i562+EdJj+oUpkqWp2R1iCoR8f6oo8STRu3of7WJJ0TqWtxN50a5YFpzYK4Jj9esYfQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/find-index": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", + "integrity": "sha512-uJ5vWrfBKMcE6y2Z8834dwEZj9mNGxYa3t3I53OwFeuZ8D9oc2E5zcsrkuhX6h4iYrjhiv0T3szQmxlAV9uxDg==" + }, + "node_modules/find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==", + "dev": true, + "dependencies": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/find-up/node_modules/path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==", + "dev": true, + "dependencies": { + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dev": true, + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dependencies": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/fined/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/first-chunk-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz", + "integrity": "sha512-X8Z+b/0L4lToKYq+lwnKqi9X/Zek0NibLpsJgVsSxpoYq7JtiCtRb5HqKVEjEw/qAb/4AKKRLOwwKHlWNpm2Eg==", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==", + "dependencies": { + "for-in": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", + "dependencies": { + "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/fs-mkdirp-stream/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/gaze": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", + "integrity": "sha512-3IWbXGkDDHFX8zIlNdfnmhvlSMhpBO6tDr4InB8fGku6dh/gjFPGNqcdsXJajZg05x9jRzXbL6gCnCnuMap4tw==", + "dependencies": { + "globule": "~0.1.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "node_modules/get-intrinsic": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", + "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha512-ab1S1g1EbO7YzauaJLkgLp7DZVAqj9M/dvKlTt8DkXA2tiOIcSMrlVI2J1RZyB5iJVccEscjGn+kpOG9788MHA==", + "dev": true, + "dependencies": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-base/node_modules/glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha512-JDYOvfxio/t42HKdxkAYaCiBN7oYiuxykOxKxdaUW5Qn0zaYN3gRQWolrwdnf0shM9/EP0ebuuTmyoXNr1cC5w==", + "dev": true, + "dependencies": { + "is-glob": "^2.0.0" + } + }, + "node_modules/glob-base/node_modules/is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-base/node_modules/is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==", + "dev": true, + "dependencies": { + "is-extglob": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==", + "dev": true, + "dependencies": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/glob-watcher": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", + "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "normalize-path": "^3.0.0", + "object.defaults": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/glob2base": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "integrity": "sha512-ZyqlgowMbfj2NPjxaZZ/EtsXlOch28FRXgMd64vqZWk1bT9+wvSRLYD1om9M7QfQru51zJPAT17qXm4/zd+9QA==", + "dependencies": { + "find-index": "^0.1.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dependencies": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", + "dependencies": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/globule": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "integrity": "sha512-3eIcA2OjPCm4VvwIwZPzIxCVssA8HSpM2C6c6kK5ufJH4FGwWoyqL3In19uuX4oe+TwH3w2P1nQDmW56iehO4A==", + "dependencies": { + "glob": "~3.1.21", + "lodash": "~1.0.1", + "minimatch": "~0.2.11" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/globule/node_modules/glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha512-ANhy2V2+tFpRajE3wN4DhkNQ08KDr0Ir1qL12/cUe5+a7STEK8jkW4onUYuY8/06qAFuT5je7mjAqzx0eKI2tQ==", + "dependencies": { + "graceful-fs": "~1.2.0", + "inherits": "1", + "minimatch": "~0.2.11" + }, + "engines": { + "node": "*" + } + }, + "node_modules/globule/node_modules/graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha512-iiTUZ5vZ+2ZV+h71XAgwCSu6+NAizhFU3Yw8aC/hH5SQ3SnISqEqAek40imAFGtDcwJKNhXvSY+hzIolnLwcdQ==", + "deprecated": "please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/globule/node_modules/inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha512-Al67oatbRSo3RV5hRqIoln6Y5yMVbJSIn4jEJNL7VCImzq/kLr7vvb6sFRJXqr8rpHc/2kJOM+y0sPKN47VdzA==" + }, + "node_modules/globule/node_modules/lodash": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "integrity": "sha512-0VSEDVec/Me2eATuoiQd8IjyBMMX0fahob8YJ96V1go2RjvCk1m1GxmtfXn8RNSaLaTtop7fsuhhu9oLk3hUgA==", + "engines": [ + "node", + "rhino" + ] + }, + "node_modules/globule/node_modules/minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha512-zZ+Jy8lVWlvqqeM8iZB7w7KmQkoJn8djM585z88rywrEbzoqawVa9FR5p2hwD+y74nfuKOjmNvi9gtWJNLqHvA==", + "deprecated": "Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue", + "dependencies": { + "lru-cache": "2", + "sigmund": "~1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/glogg": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", + "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", + "dependencies": { + "sparkles": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "node_modules/growly": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", + "integrity": "sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw==" + }, + "node_modules/gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "dev": true, + "dependencies": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + }, + "bin": { + "gulp": "bin/gulp.js" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-autoprefixer": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/gulp-autoprefixer/-/gulp-autoprefixer-6.1.0.tgz", + "integrity": "sha512-Ti/BUFe+ekhbDJfspZIMiOsOvw51KhI9EncsDfK7NaxjqRm+v4xS9v99kPxEoiDavpWqQWvG8Y6xT1mMlB3aXA==", + "dev": true, + "dependencies": { + "autoprefixer": "^9.5.1", + "fancy-log": "^1.3.2", + "plugin-error": "^1.0.1", + "postcss": "^7.0.2", + "through2": "^3.0.1", + "vinyl-sourcemaps-apply": "^0.2.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/gulp-cli": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", + "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", + "dev": true, + "dependencies": { + "ansi-colors": "^1.0.1", + "archy": "^1.0.0", + "array-sort": "^1.0.0", + "color-support": "^1.1.3", + "concat-stream": "^1.6.0", + "copy-props": "^2.0.1", + "fancy-log": "^1.3.2", + "gulplog": "^1.0.0", + "interpret": "^1.4.0", + "isobject": "^3.0.1", + "liftoff": "^3.1.0", + "matchdep": "^2.0.0", + "mute-stdout": "^1.0.0", + "pretty-hrtime": "^1.0.0", + "replace-homedir": "^1.0.0", + "semver-greatest-satisfied-range": "^1.1.0", + "v8flags": "^3.2.0", + "yargs": "^7.1.0" + }, + "bin": { + "gulp": "bin/gulp.js" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-concat": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", + "integrity": "sha512-a2scActrQrDBpBbR3WUZGyGS1JEPLg5PZJdIa7/Bi3GuKAmPYDK6SFhy/NZq5R8KsKKFvtfR0fakbUCcKGCCjg==", + "dev": true, + "dependencies": { + "concat-with-sourcemaps": "^1.0.0", + "through2": "^2.0.0", + "vinyl": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-concat/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/gulp-line-ending-corrector": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/gulp-line-ending-corrector/-/gulp-line-ending-corrector-1.0.3.tgz", + "integrity": "sha512-l68bon1Bbni5S5boKqya3MiwDGn8f6XGV7fsmOokkS+etVk/LY+OhFm24xy0Jlo8Xf0Rx4LsDNhmdzUGIaw7Yg==", + "dev": true, + "dependencies": { + "coffeescript": "^2.0.3", + "line-ending-corrector": "^1.0.1", + "plugin-error": "^1.0.1", + "through2": "^2.0.0" + } + }, + "node_modules/gulp-line-ending-corrector/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/gulp-messenger": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/gulp-messenger/-/gulp-messenger-0.28.2.tgz", + "integrity": "sha512-QXzzeLFDs1WazQT5eWVvdl7XpMhj9f/WXxouI8sqSdplXoe8GPJXSpRGcqRY4Xcfc7ecdIWo1GVgZLLvDUczIw==", + "dependencies": { + "ansi-styles": "3.0.0", + "bowser": "^1.6.0", + "chalk": "^2.0.1", + "chalkline": "0.0.5", + "defaults": "1.0.3", + "detect-node": "^2.0.3", + "easy-table": "^1.0.0", + "gulp": "3.9.1", + "is_js": "^0.9.0", + "lodash": "^3.10.1", + "lodash-deep": "^1.6.0", + "lodash._getnative": "^3.9.1", + "lodash.isarguments": "^3.1.0", + "lodash.isarray": "^4.0.0", + "mkdirp": "^0.5.1", + "moment": "^2.17.1", + "path-exists": "3.0.0", + "pretty-hrtime": "^1.0.3", + "purdy": "^2.2.0", + "sprintf-js": "1.0.3", + "through2": "^2.0.3", + "up": "^1.0.2", + "winston": "^2.3.1" + } + }, + "node_modules/gulp-messenger/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-messenger/node_modules/ansi-styles": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.0.0.tgz", + "integrity": "sha512-caosO5GROQ6HZCO0PCuqFmKb0g2ow+7fvz60N3/A3ggyeDnFvLjW8mLR84eK/6hsh206bSm3s3j34bLKJPcnLw==", + "dependencies": { + "color-convert": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/gulp-messenger/node_modules/clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha512-g62n3Kb9cszeZvmvBUqP/dsEJD/+80pDA8u8KqHnAPrVnQ2Je9rVV6opxkhuWCd1kCn2gOibzDKxCtBvD3q5kA==", + "engines": { + "node": "*" + } + }, + "node_modules/gulp-messenger/node_modules/clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha512-dhUqc57gSMCo6TX85FLfe51eC/s+Im2MLkAgJwfaRRexR2tA4dd3eLEW4L6efzHc2iNorrRRXITifnDLlRrhaA==" + }, + "node_modules/gulp-messenger/node_modules/findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha512-vs+3unmJT45eczmcAZ6zMJtxN3l/QXeccaXQx5cu/MeJMhewVfoWZqibRkOxPnmoR59+Zy5hjabfQc6JLSah4g==", + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-messenger/node_modules/first-chunk-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha512-ArRi5axuv66gEsyl3UuK80CzW7t56hem73YGNYxNWTGNKFJUadSb9Gu9SHijYEUi8ulQMf1bJomYNwSCPHhtTQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-messenger/node_modules/glob": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha512-I0rTWUKSZKxPSIAIaqhSXTM/DiII6wame+rEC3cFA5Lqmr9YmdL7z6Hj9+bdWtTvoY1Su4/OiMLmb37Y7JzvJQ==", + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^2.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/gulp-messenger/node_modules/glob-stream": { + "version": "3.1.18", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "integrity": "sha512-owHtlMMXIAbxLjhUAO0HhW1/TB7kV0AwDduI3BLbYsWCaRzNIcLBu8N0wHZft2Za2SCmUXCEOdpZzC7k/H19eg==", + "dependencies": { + "glob": "^4.3.1", + "glob2base": "^0.0.12", + "minimatch": "^2.0.1", + "ordered-read-streams": "^0.1.0", + "through2": "^0.6.1", + "unique-stream": "^1.0.0" + }, + "engines": { + "node": ">= 0.9" + } + }, + "node_modules/gulp-messenger/node_modules/glob-stream/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/gulp-messenger/node_modules/glob-stream/node_modules/through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha512-RkK/CCESdTKQZHdmKICijdKKsCRVHs5KsLZ6pACAmF/1GPUQhonHSXWNERctxEp7RmvjdNbZTL5z9V7nSCXKcg==", + "dependencies": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + }, + "node_modules/gulp-messenger/node_modules/glob-watcher": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "integrity": "sha512-lzYWq1BJLBmtb9rzT6+lgbFlEW6Sc7B+Qs3RmsNA9lbdFSqLHhebfypPR3nbEOMeEQyawVXqSDH0aqjtImldow==", + "dependencies": { + "gaze": "^0.5.1" + }, + "engines": { + "node": ">= 0.9" + } + }, + "node_modules/gulp-messenger/node_modules/graceful-fs": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.12.tgz", + "integrity": "sha512-J55gaCS4iTTJfTXIxSVw3EMQckcqkpdRv3IR7gu6sq0+tbC363Zx6KH/SEwXASK9JRbhyZmVjJEVJIOxYsB3Qg==", + "dependencies": { + "natives": "^1.1.3" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/gulp-messenger/node_modules/gulp": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", + "integrity": "sha512-6FHNdR+VG1LcPz6gZGGqgvimWWGtl4x3FvshAdK/UnAjU7aFOyzft3Fjp35r0Y3ZF4u8vND0S4nGsIB/sxTqzQ==", + "dependencies": { + "archy": "^1.0.0", + "chalk": "^1.0.0", + "deprecated": "^0.0.1", + "gulp-util": "^3.0.0", + "interpret": "^1.0.0", + "liftoff": "^2.1.0", + "minimist": "^1.1.0", + "orchestrator": "^0.3.0", + "pretty-hrtime": "^1.0.0", + "semver": "^4.1.0", + "tildify": "^1.0.0", + "v8flags": "^2.0.2", + "vinyl-fs": "^0.3.0" + }, + "bin": { + "gulp": "bin/gulp.js" + }, + "engines": { + "node": ">= 0.9" + } + }, + "node_modules/gulp-messenger/node_modules/gulp/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-messenger/node_modules/gulp/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-messenger/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-messenger/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-messenger/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "node_modules/gulp-messenger/node_modules/liftoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", + "integrity": "sha512-01zfGFqfORP1CGmZZP2Zn51zsqz4RltDi0RDOhbGoLYdUT5Lw+I2gX6QdwXhPITF6hPOHEOp+At6/L24hIg9WQ==", + "dependencies": { + "extend": "^3.0.0", + "findup-sync": "^2.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/gulp-messenger/node_modules/lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha512-9mDDwqVIma6OZX79ZlDACZl8sBm0TEnkf99zV3iMA4GzkIT/9hiqP5mY0HoT1iNLCrKc/R1HByV+yJfRWVJryQ==" + }, + "node_modules/gulp-messenger/node_modules/minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha512-jQo6o1qSVLEWaw3l+bwYA2X0uLuK2KjNh2wjgO7Q/9UJnXr1Q3yQKR8BI0/Bt/rPg75e6SMW4hW/6cBHVTZUjA==", + "deprecated": "Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue", + "dependencies": { + "brace-expansion": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/gulp-messenger/node_modules/ordered-read-streams": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "integrity": "sha512-PMX5ehiNri4+lgk9fl09xuPeciGmyPyVUSBwwPT4C/3EHGxoVf7UdgKDE3SLBD4pUDmlzrg1L1cK5igrp+Tyuw==" + }, + "node_modules/gulp-messenger/node_modules/semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha512-IrpJ+yoG4EOH8DFWuVg+8H1kW1Oaof0Wxe7cPcXW3x9BjkN/eVo54F15LyqemnDIUYskQWr9qvl/RihmSy6+xQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/gulp-messenger/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" + }, + "node_modules/gulp-messenger/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-messenger/node_modules/strip-bom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "integrity": "sha512-qVAeAIjblKDp/8Cd0tJdxpe3Iq/HooI7En98alEaMbz4Wedlrcj3WI72dDQSrziRW5IQ0zeBo3JXsmS8RcS9jg==", + "dependencies": { + "first-chunk-stream": "^1.0.0", + "is-utf8": "^0.2.0" + }, + "bin": { + "strip-bom": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-messenger/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/gulp-messenger/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/gulp-messenger/node_modules/unique-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", + "integrity": "sha512-L8KM6TdpsoBk6TJTXevbmpub3bATS06Znu3BcfVPVQkFtnh1MFeCZ3gFKCQcji7f7YYiigsO5OR99vqhoNT8nQ==" + }, + "node_modules/gulp-messenger/node_modules/v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha512-SKfhk/LlaXzvtowJabLZwD4K6SGRYeoxA7KJeISlUMAB/NT4CBkZjMq3WceX2Ckm4llwqYVo8TICgsDYCBU2tA==", + "dependencies": { + "user-home": "^1.1.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/gulp-messenger/node_modules/vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha512-pmza4M5VA15HOImIQYWhoXGlGNafCm0QK5BpBUXkzzEwrRxKqBsbAhTfkT2zMcJhUX1G1Gkid0xaV8WjOl7DsA==", + "dependencies": { + "clone": "^0.2.0", + "clone-stats": "^0.0.1" + }, + "engines": { + "node": ">= 0.9" + } + }, + "node_modules/gulp-messenger/node_modules/vinyl-fs": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", + "integrity": "sha512-9CTKjt8378nhdydwFDTwywKio0n8aqq6xA70g0uypcnTNSCow/gQOwv0L9E2GaKd7EQ3kZl/diBxPSCgcBXESw==", + "dependencies": { + "defaults": "^1.0.0", + "glob-stream": "^3.1.5", + "glob-watcher": "^0.0.6", + "graceful-fs": "^3.0.0", + "mkdirp": "^0.5.0", + "strip-bom": "^1.0.0", + "through2": "^0.6.1", + "vinyl": "^0.4.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-messenger/node_modules/vinyl-fs/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/gulp-messenger/node_modules/vinyl-fs/node_modules/through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha512-RkK/CCESdTKQZHdmKICijdKKsCRVHs5KsLZ6pACAmF/1GPUQhonHSXWNERctxEp7RmvjdNbZTL5z9V7nSCXKcg==", + "dependencies": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + }, + "node_modules/gulp-notify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/gulp-notify/-/gulp-notify-3.0.0.tgz", + "integrity": "sha512-xMK/3J7rOF9+97NMCzuZmgYx0xCmwswaCKMSdIU/2VV4GzuZGexY0CtFtN/zR4+OmAHy5Zx2w8FGn89Xk90UUw==", + "dependencies": { + "gulp-util": "^3.0.8", + "lodash.template": "^4.4.0", + "node-notifier": "^5.0.1", + "node.extend": "^1.1.6", + "through2": "^2.0.3" + }, + "engines": { + "node": ">=0.8.0", + "npm": ">=1.2.10" + } + }, + "node_modules/gulp-notify/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/gulp-phpunit": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/gulp-phpunit/-/gulp-phpunit-0.26.0.tgz", + "integrity": "sha512-px1/qpMpHjgdoKYCMmZAyXwquKxMMUU5OQCYDNYZxnnlTJKK79hU4CqR1Hhdb6/N9H05zcX3Fbnx2O4lsB0wMA==", + "dependencies": { + "chalk": "^2.0.1", + "chalkline": "0.0.5", + "gulp-messenger": "^0.28.2", + "gulp-notify": "3.0.0", + "lodash": "^4.15.0", + "map-stream": "~0.0.4", + "node-notifier": "5.0.2", + "plugin-error": "^0.1.2", + "shelljs": "0.7.6" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-phpunit/node_modules/arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha512-OQwDZUqYaQwyyhDJHThmzId8daf4/RFNLaeh3AevmSeZ5Y7ug4Ga/yKc6l6kTZOBW781rCj103ZuTh8GAsB3+Q==", + "dependencies": { + "arr-flatten": "^1.0.1", + "array-slice": "^0.2.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-phpunit/node_modules/arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha512-t5db90jq+qdgk8aFnxEkjqta0B/GHrM1pxzuuZz2zWsOXc5nKu3t+76s/PQBA8FTcM/ipspIH9jWG4OxCBc2eA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-phpunit/node_modules/array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha512-rlVfZW/1Ph2SNySXwR9QYkChp8EkOEiTMO5Vwx60usw04i4nWemkm9RXmQqgkQFaLHsqLuADvjp6IfgL9l2M8Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-phpunit/node_modules/extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha512-L7AGmkO6jhDkEBBGWlLtftA80Xq8DipnrRPr0pyi7GQLXkaq9JYA4xF4z6qnadIC6euiTDKco0cGSU9muw+WTw==", + "dependencies": { + "kind-of": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-phpunit/node_modules/kind-of": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha512-aUH6ElPnMGon2/YkxRIigV32MOpTVcoXQ1Oo8aYn40s+sJ3j+0gFZsT8HKDcxNy7Fi9zuquWtGaGAahOdv5p/g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-phpunit/node_modules/plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha512-WzZHcm4+GO34sjFMxQMqZbsz3xiNEgonCskQ9v+IroMmYgk/tas8dG+Hr2D6IbRPybZ12oWpzE/w3cGJ6FJzOw==", + "dependencies": { + "ansi-cyan": "^0.1.1", + "ansi-red": "^0.1.1", + "arr-diff": "^1.0.1", + "arr-union": "^2.0.1", + "extend-shallow": "^1.1.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-rename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-2.0.0.tgz", + "integrity": "sha512-97Vba4KBzbYmR5VBs9mWmK+HwIf5mj+/zioxfZhOKeXtx5ZjBk57KFlePf5nxq9QsTtFl0ejnHE3zTC9MHXqyQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/gulp-sass": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/gulp-sass/-/gulp-sass-5.1.0.tgz", + "integrity": "sha512-7VT0uaF+VZCmkNBglfe1b34bxn/AfcssquLKVDYnCDJ3xNBaW7cUuI3p3BQmoKcoKFrs9jdzUxyb+u+NGfL4OQ==", + "dev": true, + "dependencies": { + "lodash.clonedeep": "^4.5.0", + "picocolors": "^1.0.0", + "plugin-error": "^1.0.1", + "replace-ext": "^2.0.0", + "strip-ansi": "^6.0.1", + "vinyl-sourcemaps-apply": "^0.2.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/gulp-sass/node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/gulp-uglify": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.2.tgz", + "integrity": "sha512-gk1dhB74AkV2kzqPMQBLA3jPoIAPd/nlNzP2XMDSG8XZrqnlCiDGAqC+rZOumzFvB5zOphlFh6yr3lgcAb/OOg==", + "dev": true, + "dependencies": { + "array-each": "^1.0.1", + "extend-shallow": "^3.0.2", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "isobject": "^3.0.1", + "make-error-cause": "^1.1.1", + "safe-buffer": "^5.1.2", + "through2": "^2.0.0", + "uglify-js": "^3.0.5", + "vinyl-sourcemaps-apply": "^0.2.0" + } + }, + "node_modules/gulp-uglify/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-uglify/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-uglify/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-uglify/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha512-q5oWPc12lwSFS9h/4VIjG+1NuNDlJ48ywV2JKItY4Ycc/n1fXJeYPVQsfu5ZrhQi7FGSDBalwUCLar/GyHXKGw==", + "deprecated": "gulp-util is deprecated - replace it, following the guidelines at https://medium.com/gulpjs/gulp-util-ca3b1f9f9ac5", + "dependencies": { + "array-differ": "^1.0.0", + "array-uniq": "^1.0.2", + "beeper": "^1.0.0", + "chalk": "^1.0.0", + "dateformat": "^2.0.0", + "fancy-log": "^1.1.0", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "lodash._reescape": "^3.0.0", + "lodash._reevaluate": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.template": "^3.0.0", + "minimist": "^1.1.0", + "multipipe": "^0.1.2", + "object-assign": "^3.0.0", + "replace-ext": "0.0.1", + "through2": "^2.0.0", + "vinyl": "^0.5.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/gulp-util/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-util/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-util/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-util/node_modules/clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha512-dhUqc57gSMCo6TX85FLfe51eC/s+Im2MLkAgJwfaRRexR2tA4dd3eLEW4L6efzHc2iNorrRRXITifnDLlRrhaA==" + }, + "node_modules/gulp-util/node_modules/lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha512-0B4Y53I0OgHUJkt+7RmlDFWKjVAI/YUpWNiL9GQz5ORDr4ttgfQGo+phBWKFLJbBdtOwgMuUkdOHOnPg45jKmQ==", + "dependencies": { + "lodash._basecopy": "^3.0.0", + "lodash._basetostring": "^3.0.0", + "lodash._basevalues": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0", + "lodash.keys": "^3.0.0", + "lodash.restparam": "^3.0.0", + "lodash.templatesettings": "^3.0.0" + } + }, + "node_modules/gulp-util/node_modules/lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha512-TcrlEr31tDYnWkHFWDCV3dHYroKEXpJZ2YJYvJdhN+y4AkWMDZ5I4I8XDtUKqSAyG81N7w+I1mFEJtcED+tGqQ==", + "dependencies": { + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" + } + }, + "node_modules/gulp-util/node_modules/replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha512-AFBWBy9EVRTa/LhEcG8QDP3FvpwZqmvN2QFDuJswFeaVhWnZMp8q3E6Zd90SR04PlIwfGdyVjNyLPyen/ek5CQ==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gulp-util/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-util/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/gulp-util/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/gulp-util/node_modules/vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha512-P5zdf3WB9uzr7IFoVQ2wZTmUwHL8cMZWJGzLBNCHNZ3NB6HTMsYABtt7z8tAGIINLXyAob9B9a1yzVGMFOYKEA==", + "dependencies": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + }, + "engines": { + "node": ">= 0.9" + } + }, + "node_modules/gulp-watch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/gulp-watch/-/gulp-watch-5.0.1.tgz", + "integrity": "sha512-HnTSBdzAOFIT4wmXYPDUn783TaYAq9bpaN05vuZNP5eni3z3aRx0NAKbjhhMYtcq76x4R1wf4oORDGdlrEjuog==", + "dev": true, + "dependencies": { + "ansi-colors": "1.1.0", + "anymatch": "^1.3.0", + "chokidar": "^2.0.0", + "fancy-log": "1.3.2", + "glob-parent": "^3.0.1", + "object-assign": "^4.1.0", + "path-is-absolute": "^1.0.1", + "plugin-error": "1.0.1", + "readable-stream": "^2.2.2", + "slash": "^1.0.0", + "vinyl": "^2.1.0", + "vinyl-file": "^2.0.0" + } + }, + "node_modules/gulp-watch/node_modules/anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "dependencies": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + } + }, + "node_modules/gulp-watch/node_modules/arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha512-dtXTVMkh6VkEEA7OhXnN1Ecb8aAGFdZ1LFxtOCoqj4qkyOJMt7+qs6Ahdy6p/NQCPYsRSXXivhSB/J5E9jmYKA==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-watch/node_modules/array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha512-G2n5bG5fSUCpnsXz4+8FUkYsGPkNfLn9YvS66U5qbTIXI2Ynnlo4Bi42bWv+omKUCqz+ejzfClwne0alJWJPhg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-watch/node_modules/braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha512-xU7bpz2ytJl1bH9cgIurjpg/n8Gohy9GTw81heDYLJQ4RU60dlyJsa+atVF2pI0yMMvKxI9HkKwjePCj5XI1hw==", + "dev": true, + "dependencies": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-watch/node_modules/expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha512-hxx03P2dJxss6ceIeri9cmYOT4SRs3Zk3afZwWpOsRqLqprhTR8u++SlC+sFGsQr7WGFPdMF7Gjc1njDLDK6UA==", + "dev": true, + "dependencies": { + "is-posix-bracket": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-watch/node_modules/extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha512-1FOj1LOwn42TMrruOHGt18HemVnbwAmAak7krWk+wa93KXxGbK+2jpezm+ytJYDaBX0/SPLZFHKM7m+tKobWGg==", + "dev": true, + "dependencies": { + "is-extglob": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-watch/node_modules/fancy-log": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha512-7E6IFy84FpO6jcnzEsCcoxDleHpMTFzncmCXXBIVYq1/Oakqnbc/lTKPJyyW6edGeC/rnZmV78hJe7SuoZo0aQ==", + "dev": true, + "dependencies": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "time-stamp": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-watch/node_modules/is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-watch/node_modules/is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==", + "dev": true, + "dependencies": { + "is-extglob": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-watch/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-watch/node_modules/micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha512-LnU2XFEk9xxSJ6rfgAry/ty5qwUTyHYOBU0g4R6tIw5ljwgGIBmiKhRWLw5NpMOnrgUNcDJ4WMp8rl3sYVHLNA==", + "dev": true, + "dependencies": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-watch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-watch/node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha512-hm6N8nrm3Y08jXie48jsC55eCZz9mnb4OirAStEk2deqeyhXU3C1otDVh+ccttMuc1sBi6RX6ZJ720hs9RCvgw==", + "dependencies": { + "glogg": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-color": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", + "integrity": "sha512-kaNz5OTAYYmt646Hkqw50/qyxP2vFnTVu5AQ1Zmk22Kk5+4Qx6BpO8+u7IKsML5fOsFk0ZT0AcCJNYwcvaLBvw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha512-+F4GzLjwHNNDEAJW2DC1xXfEoPkRDmUdJ7CBYw4MpqtDwOnqdImJl7GWlpqx+Wko6//J8uKTnIe4wZSv7yCqmw==", + "dependencies": { + "sparkles": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==", + "dependencies": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==", + "dependencies": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha512-V6Yw1rIcYV/4JsnggjBU0l4Kr+EXhpwqXRusENU1Xx6ro00IHPHYNynCuBTOZAPlr3AAmLvchH9I7N/VUdvOwQ==", + "deprecated": "This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).", + "engines": { + "node": ">=0.10.40" + } + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/immutable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz", + "integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==", + "dev": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/is/-/is-3.3.0.tgz", + "integrity": "sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg==", + "engines": { + "node": "*" + } + }, + "node_modules/is_js": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/is_js/-/is_js-0.9.0.tgz", + "integrity": "sha512-8Y5EHSH+TonfUHX2g3pMJljdbGavg55q4jmHzghJCdqYDbdNROC8uw/YFQwIRCRqRJT1EY3pJefz+kglw+o7sg==" + }, + "node_modules/is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dependencies": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", + "dev": true, + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "node_modules/is-core-module": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-descriptor/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha512-9YclgOGtN/f8zx0Pr4FQYMdibBiTaH3sn52vjYip4ZSf6C4/6RfTEZ+MR4GvKhCxdPh21Bg42/WL55f6KSnKpg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha512-0EygVC5qPvIyb+gSz7zdD5/AAoS6Qrx1e//6N4yv4oNm30kqvdmG66oZFWVlQHUWe5OjP08FuTw2IdT0EOTcYA==", + "dev": true, + "dependencies": { + "is-primitive": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dev": true, + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha512-Yu68oeXJ7LeWNmZ3Zov/xg/oDBnBK2RNxwYY1ilNJX+tKKZqgPK+qOn/Gs9jEu66KDY9Netf5XLKNGzas/vPfQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha512-N3w1tFaRfk3UrPfqeRyD+GYDASU3W5VinKhlORy8EWVf/sIdDL9GAcew85XmktCfH+ngG7SRXEVDoO18WMdB/Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dependencies": { + "is-unc-path": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dependencies": { + "unc-path-regex": "^0.1.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==" + }, + "node_modules/is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/isemail": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz", + "integrity": "sha512-pZMb1rDrWRAPtVY92VCxWtF+1gExWrCnao+GL1EKHx6z19ovW+xNcnC1iNB7WkbSYWlyl3uwlaH5eaBx2s2crw==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" + }, + "node_modules/joi": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz", + "integrity": "sha512-K6+OwGaWM1sBEu+XMbgC4zDmg6hnddS2DWiCVtjnhkcrzv+ejSfh7HGUsoxmWQkv6kHEsVFAywttfkpmIE2QwQ==", + "deprecated": "This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).", + "dependencies": { + "hoek": "2.x.x", + "isemail": "1.x.x", + "moment": "2.x.x", + "topo": "1.x.x" + }, + "engines": { + "node": ">=0.10.40", + "npm": ">=2.0.0" + } + }, + "node_modules/js2xmlparser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", + "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", + "dev": true, + "dependencies": { + "xmlcreate": "^2.0.4" + } + }, + "node_modules/jsdoc": { + "version": "3.6.11", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.11.tgz", + "integrity": "sha512-8UCU0TYeIYD9KeLzEcAu2q8N/mx9O3phAGl32nmHlE0LpaJL71mMkP4d+QE5zWfNt50qheHtOZ0qoxVrsX5TUg==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.9.4", + "@types/markdown-it": "^12.2.3", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^12.3.2", + "markdown-it-anchor": "^8.4.1", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "taffydb": "2.6.2", + "underscore": "~1.13.2" + }, + "bin": { + "jsdoc": "jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/jsdoc/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jsdoc/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/just-debounce": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.1.0.tgz", + "integrity": "sha512-qpcRocdkUmf+UTNBYx5w6dexX5J31AKK1OmPwH630a83DdVVUIngk55RSAiIGpQyoH0dlr872VHfPjnQnK1qDQ==", + "dev": true + }, + "node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.9" + } + }, + "node_modules/last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha512-U/VxvpX4N/rFvPzr3qG5EtLKEnNI0emvIQB3/ecEwv+8GHaUKbIB8vxv1Oai5FAF0d0r7LXHhLLe5K/yChm5GQ==", + "dev": true, + "dependencies": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw==", + "dev": true, + "dependencies": { + "invert-kv": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha512-IpSVCk9AYvLHo5ctcIXxOBpMWUe+4TKN3VPWAKUbJikkmsGp0VrSM8IttVc32D6J4WUsiPE6aEFRNmIoF/gdow==", + "dev": true, + "dependencies": { + "flush-write-stream": "^1.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/liftoff": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", + "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", + "dev": true, + "dependencies": { + "extend": "^3.0.0", + "findup-sync": "^3.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/liftoff/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/line-ending-corrector": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/line-ending-corrector/-/line-ending-corrector-1.0.1.tgz", + "integrity": "sha512-uwHj4enSztzPuHdDCysaO94S2bNk8gfR2TKIzPYz2v3sDq/7L6aUxg4uZHnbDYFIdjjxhxcA/2YE7RCqpSbY+A==", + "dev": true, + "dependencies": { + "coffeescript": "^2.0.3" + } + }, + "node_modules/linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "dev": true, + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "node_modules/load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash-deep": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lodash-deep/-/lodash-deep-1.6.0.tgz", + "integrity": "sha512-KXP3vvDWAiZ3wDEcS9Hzgrk/hyaz9A2XfNsZULNmbNQwVG9eShQr4kPE70RNcxF+XSTDK9HmfSjg71BYVXBNog==", + "dependencies": { + "lodash": ">=2.4.1" + }, + "engines": { + "node": ">=0.8.0", + "npm": ">=1.2.10" + } + }, + "node_modules/lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha512-rFR6Vpm4HeCK1WPGvjZSJ+7yik8d8PVUdCJx5rT2pogG4Ve/2ZS7kfmO5l5T2o5V2mqlNIfSF5MZlr1+xOoYQQ==" + }, + "node_modules/lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha512-mTzAr1aNAv/i7W43vOR/uD/aJ4ngbtsRaCubp2BfZhlGU/eORUjg/7F6X0orNMdv33JOrdgGybtvMN/po3EWrA==" + }, + "node_modules/lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha512-H94wl5P13uEqlCg7OcNNhMQ8KvWSIyqXzOPusRgHC9DK3o54P6P3xtbXlVbRABG4q5gSmp7EDdJ0MSuW9HX6Mg==" + }, + "node_modules/lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha512-RrL9VxMEPyDMHOd9uFbvMe8X55X16/cGM5IgOKgRElQZutpX89iS6vwl64duTV1/16w5JY7tuFNXqoekmh1EmA==" + }, + "node_modules/lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha512-De+ZbrMu6eThFti/CSzhRvTKMgQToLxbij58LMfM8JnYDNSOjkjTCIaa8ixglOeGh2nyPlakbt5bJWJ7gvpYlQ==" + }, + "node_modules/lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha512-Sjlavm5y+FUVIF3vF3B75GyXrzsfYV8Dlv3L4mEpuB9leg8N6yf/7rU06iLPx9fY0Mv3khVp9p7Dx0mGV6V5OQ==" + }, + "node_modules/lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha512-OrPwdDc65iJiBeUe5n/LIjd7Viy99bKwDdk7Z5ljfZg0uFRFlfQaCy9tZ4YMAag9WAZmlVpe1iZrkIMMSMHD3w==" + }, + "node_modules/lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==" + }, + "node_modules/lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha512-O0pWuFSK6x4EXhM1dhZ8gchNtG7JMqBtrHdoUFUWXD7dJnNSUze1GuyQr5sOs0aCvgGeI3o/OJW8f4ca7FDxmQ==" + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "dev": true + }, + "node_modules/lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha512-n1PZMXgaaDWZDSvuNZ/8XOcYO2hOKDqZel5adtR30VKQAtoWs/5AOeFA0vPV8moiPzlqe7F4cP2tzpFewQyelQ==", + "dependencies": { + "lodash._root": "^3.0.0" + } + }, + "node_modules/lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" + }, + "node_modules/lodash.isarray": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-4.0.0.tgz", + "integrity": "sha512-V8ViWvoNlXpCrB6Ewaj3ScRXUpmCvqp4tJUxa3dlovuJj/8lp3SND5Kw4v5OeuHgoyw4qJN+gl36qZqp6WYQ6g==", + "deprecated": "This package is deprecated. Use Array.isArray." + }, + "node_modules/lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha512-CuBsapFjcubOGMn3VD+24HOAPxM79tH+V6ivJL3CHYjtrawauDJHUk//Yew9Hvc6e9rbCrURGk8z6PC+8WJBfQ==", + "dependencies": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, + "node_modules/lodash.keys/node_modules/lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha512-JwObCrNJuT0Nnbuecmqr5DgtuBppuCvGD9lxjFpAzwnVtdGoDQ1zig+5W8k5/6Gcn0gZ3936HDAlGd28i7sOGQ==" + }, + "node_modules/lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha512-L4/arjjuq4noiUJpt3yS6KIKDtJwNe2fIYgMqyYYKoeIfV1iEqvPwhCx23o+R9dzouGihDAPN1dTIRWa7zk8tw==" + }, + "node_modules/lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "dependencies": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "node_modules/lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "dependencies": { + "lodash._reinterpolate": "^3.0.0" + } + }, + "node_modules/lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha512-WpibWJ60c3AgAz8a2iYErDrcT2C7OmKnsWhIcHOjkUHFjkXncJhtLxNSqUmxRxRunpb5I8Vprd7aNSd2NtksJQ==" + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/make-error-cause": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", + "integrity": "sha512-4TO2Y3HkBnis4c0dxhAgD/jprySYLACf7nwN6V0HAHDx59g12WlRpUmFy1bRHamjGUEEBrEvCq6SUpsEE2lhUg==", + "dev": true, + "dependencies": { + "make-error": "^1.2.0" + } + }, + "node_modules/make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/make-iterator/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", + "integrity": "sha512-C0X0KQmGm3N2ftbTGBhSyuydQ+vV1LC3f3zPvT3RXHXNZrvfPZcoXp/N5DOa8vedX/rTMm2CjTtivFg2STJMRQ==" + }, + "node_modules/map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==", + "dependencies": { + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/markdown-it": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/markdown-it-anchor": { + "version": "8.6.4", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.4.tgz", + "integrity": "sha512-Ul4YVYZNxMJYALpKtu+ZRdrryYt/GlQ5CK+4l1bp/gWXOG2QWElt6AqF3Mih/wfUKdZbNAZVXGR73/n6U/8img==", + "dev": true, + "peerDependencies": { + "@types/markdown-it": "*", + "markdown-it": "*" + } + }, + "node_modules/marked": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.18.tgz", + "integrity": "sha512-wbLDJ7Zh0sqA0Vdg6aqlbT+yPxqLblpAZh1mK2+AO2twQkPywvvqQNfEPVwSSRjZ7dZcdeVBIAgiO7MMp3Dszw==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/matchdep": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", + "integrity": "sha512-LFgVbaHIHMqCRuCZyfCtUOq9/Lnzhi7Z0KFUE2fhD54+JN2jLh3hC02RLkqauJ3U4soU6H1J3tfj/Byk7GoEjA==", + "dev": true, + "dependencies": { + "findup-sync": "^2.0.0", + "micromatch": "^3.0.4", + "resolve": "^1.4.0", + "stack-trace": "0.0.10" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/matchdep/node_modules/findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha512-vs+3unmJT45eczmcAZ6zMJtxN3l/QXeccaXQx5cu/MeJMhewVfoWZqibRkOxPnmoR59+Zy5hjabfQc6JLSah4g==", + "dev": true, + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/matchdep/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/math-random": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", + "dev": true + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "dev": true + }, + "node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "node_modules/mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dependencies": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mixin-deep/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mixin-deep/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha512-7ZxrUybYv9NonoXgwoOqtStIu18D1c3eFZj27hqgf5kBrBF8Q+tE8V0MW8dKM5QLkQPh1JhhbKgHLY9kifov4Q==", + "dependencies": { + "duplexer2": "0.0.2" + } + }, + "node_modules/mute-stdout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", + "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==", + "dev": true, + "optional": true + }, + "node_modules/nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/natives": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.6.tgz", + "integrity": "sha512-6+TDFewD4yxY14ptjKaS63GVdtKiES1pTPyxn9Jb0rBqPMZ7VcCiooEhPNsr+mqHtMGxa/5c/HhcC4uPEUw/nA==", + "deprecated": "This module relies on Node.js's internals and will break at some point. Do not use it, and update to graceful-fs@4.x." + }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "dev": true + }, + "node_modules/node-notifier": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.0.2.tgz", + "integrity": "sha512-nmc9wotRDRFGrV2zn6VmdkZjqr2dnzM23KRfMATDYt1XvlfjIqLf+THlXeO1+Wbltz04EeIO9FVVhBzQtVTZCg==", + "dependencies": { + "growly": "^1.3.0", + "semver": "^5.3.0", + "shellwords": "^0.1.0", + "which": "^1.2.12" + } + }, + "node_modules/node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": true + }, + "node_modules/node.extend": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.8.tgz", + "integrity": "sha512-L/dvEBwyg3UowwqOUTyDsGBU6kjBQOpOhshio9V3i3BMPv5YUb9+mWNN8MK0IbWqT0AqaTSONZf0aTuMMahWgA==", + "dependencies": { + "has": "^1.0.3", + "is": "^3.2.1" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "dependencies": { + "once": "^1.3.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg==", + "dev": true + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha512-jHP15vXVGeVh1HuaA2wY6lxk+whK/x4KBG88VXeRma7CCun7iGD5qPc4eYykQ9sdQvg8jkwFKsSxHln2ybW3xQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==", + "dependencies": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==", + "dependencies": { + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==", + "dependencies": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha512-3+mAJu2PLfnSVGHwIWubpOFLscJANBKuB/6A4CxBstc4aqwQY0FWcsppuy4jU5GSB95yES5JHSI+33AWuS4k6w==", + "dependencies": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha512-UiAM5mhmIuKLsOvrL+B0U2d1hXHF3bFYWIuH1LMpuV2EJEHG1Ntz06PgLEHjm6VFd87NpH8rastvPoyv6UW2fA==", + "dev": true, + "dependencies": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.omit/node_modules/for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha512-SKmowqGTJoPzLO1T0BBJpkfp3EMacCMOuH40hOUbrbzElVktk4DioXVM99QkLCyKoiuOmyjgcWMpVz2xjE7LZw==", + "dev": true, + "dependencies": { + "for-in": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.reduce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", + "integrity": "sha512-naLhxxpUESbNkRqc35oQ2scZSJueHGQNUfMW/0U37IgN6tE2dgDWg3whf+NEliy3F/QysrO48XKUz/nGPe+AQw==", + "dev": true, + "dependencies": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/orchestrator": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", + "integrity": "sha512-DrQ43ngaJ0e36j2CHyoDoIg1K4zbc78GnTQESebK9vu6hj4W5/pvfSFO/kgM620Yd0YnhseSNYsLK3/SszZ5NQ==", + "dependencies": { + "end-of-stream": "~0.1.5", + "sequencify": "~0.0.7", + "stream-consume": "~0.1.0" + } + }, + "node_modules/orchestrator/node_modules/end-of-stream": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "integrity": "sha512-go5TQkd0YRXYhX+Lc3UrXkoKU5j+m72jEP5lHWr2Nh82L8wfZtH8toKgcg4T10o23ELIMGXQdwCbl+qAXIPDrw==", + "dependencies": { + "once": "~1.3.0" + } + }, + "node_modules/orchestrator/node_modules/once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha512-6vaNInhu+CHxtONf3zw3vq4SP2DOQhjBvIa3rNcG0+P7eKWlYH6Peu7rHizSloRU2EwMz6GraLieis9Ac9+p1w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha512-Z87aSjx3r5c0ZB7bcJqIgIRX5bxR7A4aSzvIbaxd0oTkWBCOoKfuGHiKj60CHVUgg1Phm5yMZzBdt8XqRs73Mw==", + "dev": true, + "dependencies": { + "readable-stream": "^2.0.1" + } + }, + "node_modules/os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g==", + "dev": true, + "dependencies": { + "lcid": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==", + "dependencies": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha512-FC5TeK0AwXzq3tUBFtH74naWkPQCEWs4K+xMxWZBlKDWu0bVHXGZa+KKqxKidd7xwhdZ19ZNuF2uO1M/r196HA==", + "dev": true, + "dependencies": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse-glob/node_modules/is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse-glob/node_modules/is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==", + "dev": true, + "dependencies": { + "is-extglob": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==", + "dev": true, + "dependencies": { + "error-ex": "^1.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==", + "dev": true + }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==", + "dependencies": { + "path-root-regex": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "dev": true, + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/plugin-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "dev": true, + "dependencies": { + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/plugin-error/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/plugin-error/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/plugin-error/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha512-s/46sYeylUfHNjI+sA/78FAHlmIuKqI9wNnzEOGehAlUUYeObv5C2mOinXBjyUyWmJ2SfcS2/ydApH4hTF4WXQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pretty-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz", + "integrity": "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "node_modules/purdy": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/purdy/-/purdy-2.2.1.tgz", + "integrity": "sha512-hR6fMofSheE6zc3sybZTcVXZLuRt5vId1aOymjT3JneaMkh/5IwNasN33f/XABJeQ7m4ZhoT+2/Nj9L9z6NWIw==", + "dependencies": { + "chalk": "0.4.x", + "hoek": "2.x.x", + "joi": "6.x.x" + }, + "bin": { + "purdy": "bin/purdy.js" + } + }, + "node_modules/purdy/node_modules/ansi-styles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "integrity": "sha512-3iF4FIKdxaVYT3JqQuY3Wat/T2t7TRbbQ94Fu50ZUCbLy4TFbTzr90NOHQodQkNqmeEGCw8WbeP78WNi6SKYUA==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/purdy/node_modules/chalk": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "integrity": "sha512-sQfYDlfv2DGVtjdoQqxS0cEZDroyG8h6TamA6rvxwlrU5BaSLDx9xhatBYl2pxZ7gmpNaPFVwBtdGdu5rQ+tYQ==", + "dependencies": { + "ansi-styles": "~1.0.0", + "has-color": "~0.1.0", + "strip-ansi": "~0.1.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/purdy/node_modules/strip-ansi": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", + "integrity": "sha512-behete+3uqxecWlDAm5lmskaSaISA+ThQ4oNNBDTBJt0x2ppR6IPqfZNuj6BLaLJ/Sji4TPZlcRyOis8wXQTLg==", + "bin": { + "strip-ansi": "cli.js" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "dev": true, + "dependencies": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/randomatic/node_modules/is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/randomatic/node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==", + "dev": true, + "dependencies": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==", + "dev": true, + "dependencies": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "dependencies": { + "is-equal-shallow": "^0.1.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dependencies": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-not/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-not/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-not/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha512-wigO8/O08XHb8YPzpDDT+QmRANfW6vLqxfaXm1YXhnFf3AkSLyjfG3GEFg4McZkmgL7KvCj5u2KczkvSP6NfHA==", + "dev": true, + "dependencies": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/remove-bom-stream/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", + "dev": true + }, + "node_modules/repeat-element": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/replace-ext": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", + "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/replace-homedir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", + "integrity": "sha512-CHPV/GAglbIB1tnQgaiysb8H2yCy8WQ7lcEwQ/eT+kLj0QHV8LnJW0zpqpE7RSkrMSRoa+EBoag86clf7WAgSg==", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==", + "dev": true + }, + "node_modules/requizzle": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", + "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", + "dev": true, + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", + "dependencies": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha512-NYDgziiroVeDC29xq7bp/CacZERYsA9bXYd1ZmcJlF3BcrZv5pTb4NG7SjdyKDnXZ84aC4vo2u6sNKIA1LCu/A==", + "dev": true, + "dependencies": { + "value-or-function": "^3.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", + "deprecated": "https://github.com/lydell/resolve-url#deprecated" + }, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "engines": { + "node": ">=0.12" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==", + "dependencies": { + "ret": "~0.1.10" + } + }, + "node_modules/sass": { + "version": "1.54.4", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.54.4.tgz", + "integrity": "sha512-3tmF16yvnBwtlPrNBHw/H907j8MlOX8aTBnlNX1yrKx24RKcJGPyLhFUwkoKBKesR3unP93/2z14Ll8NicwQUA==", + "dev": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/sass/node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/sass/node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/sass/node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sass/node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/sass/node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sass/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/sass/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/sass/node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sass/node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/sass/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/sass/node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/semver-greatest-satisfied-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", + "integrity": "sha512-Ny/iyOzSSa8M5ML46IAx3iXc6tfOsYU2R4AXi2UpHk60Zrgyq6eqPj/xiOfS0rRl/iiQ/rdJkVjw/5cdUyCntQ==", + "dev": true, + "dependencies": { + "sver-compat": "^1.5.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/sequencify": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", + "integrity": "sha512-YL8BPm0tp6SlXef/VqYpA/ijmTsDP2ZEXzsnqjkaWS7NP7Bfvw18NboL0O8WCIjy67sOCG3MYSK1PB4GC9XdtQ==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true + }, + "node_modules/set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shelljs": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.6.tgz", + "integrity": "sha512-sK/rjl+frweS4RL1ifxTb7eIXQaliSCDN5meqwwfDIHSWU7zH2KPTa/2hS6EAgGw7wHzJ3rQHfhnLzktfagSZA==", + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "iojs": "*", + "node": ">=0.11.0" + } + }, + "node_modules/shellwords": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==" + }, + "node_modules/sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha512-fCvEXfh6NWpm+YSuY2bpXb/VIihqWA6hLsgboC+0nl71Q7N7o2eaCW8mJa/NLvQhs6jpd3VZV4UiUQlV6+lc8g==" + }, + "node_modules/slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dependencies": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dependencies": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dependencies": { + "kind-of": "^3.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "node_modules/source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "deprecated": "See https://github.com/lydell/source-map-url#deprecated" + }, + "node_modules/sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", + "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", + "dev": true + }, + "node_modules/split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", + "engines": { + "node": "*" + } + }, + "node_modules/static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==", + "dependencies": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stream-consume": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", + "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==" + }, + "node_modules/stream-exhaust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", + "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", + "dev": true + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", + "dev": true, + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==", + "dev": true, + "dependencies": { + "is-utf8": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-bom-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz", + "integrity": "sha512-yH0+mD8oahBZWnY43vxs4pSinn8SMKAdml/EOGBewoe1Y0Eitd0h2Mg3ZRiXruUW6L4P+lvZiEgbh0NgUGia1w==", + "dev": true, + "dependencies": { + "first-chunk-stream": "^2.0.0", + "strip-bom": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sver-compat": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", + "integrity": "sha512-aFTHfmjwizMNlNE6dsGmoAM4lHjL0CyiobWaFiXWSlD7cIxshW422Nb8KbXCmR6z+0ZEPY+daXJrDyh/vuwTyg==", + "dev": true, + "dependencies": { + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/taffydb": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", + "integrity": "sha512-y3JaeRSplks6NYQuCOj3ZFMO3j60rTwbuKCvZxsAraGYH2epusatvZ0baZYA01WsGqJBq/Dl6vOrMUJqyMj8kA==", + "dev": true + }, + "node_modules/through2": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "2 || 3" + } + }, + "node_modules/through2-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", + "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", + "dev": true, + "dependencies": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } + }, + "node_modules/through2-filter/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/tildify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha512-Y9q1GaV/BO65Z9Yf4NOGMuwt3SGdptkZBnaaKfTQakrDyCLiuO1Kc5wxW4xLdsjzunRtqtOdhekiUFmZbklwYQ==", + "dependencies": { + "os-homedir": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha512-gLCeArryy2yNTRzTGKbZbloctj64jkZ57hj5zdraXue6aFgd6PmvVtEyiUU+hvU0v7q08oVv8r8ev0tRo6bvgw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha512-rtwLUQEwT8ZeKQbyFJyomBRYXyE16U5VKuy0ftxLMK/PZb2fkOsg5r9kHdauuVDbsNdIBoC/HCthpidamQFXYA==", + "dev": true, + "dependencies": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dependencies": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha512-+QIz37Ly7acM4EMdw2PRN389OneM5+d844tirkGp4dPKzI5OE72V9OsbFp+CIYJDahZ41ZV05hNtcPAQUAm9/Q==", + "dev": true, + "dependencies": { + "through2": "^2.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/to-through/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/topo": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz", + "integrity": "sha512-vpmONxdZoD0R3hzH0lovwv8QmsqZmGCDE1wXW9YGD/reiDOAbPKEgRDlBCAt8u8nJhav/s/I+r+1gvdpA11x7Q==", + "deprecated": "This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).", + "dependencies": { + "hoek": "2.x.x" + }, + "engines": { + "node": ">=0.10.40" + } + }, + "node_modules/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true + }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, + "node_modules/uglify-js": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.0.tgz", + "integrity": "sha512-aTeNPVmgIMPpm1cxXr2Q/nEbvkmV8yq66F3om7X3P/cvOXQ0TMQ64Wk63iyT1gPlmdmGzjGpyLh1f3y8MZWXGg==", + "dev": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/underscore": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.4.tgz", + "integrity": "sha512-BQFnUDuAQ4Yf/cYY5LNrK9NCJFKriaRbD9uR1fTeXnBeoa97W0i41qkZfGO9pSo8I5KzjAcSY2XYtdf0oKd7KQ==", + "dev": true + }, + "node_modules/undertaker": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", + "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "fast-levenshtein": "^1.0.0", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha512-UR1khWeAjugW3548EfQmL9Z7pGMlBgXteQpr1IZeZBtnkCJQJIJ1Scj0mb9wQaPvUZ9Q17XqW6TIaPchJkyfqw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dependencies": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unique-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", + "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", + "dev": true, + "dependencies": { + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } + }, + "node_modules/unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==", + "dependencies": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==", + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/up": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/up/-/up-1.0.2.tgz", + "integrity": "sha512-PKVGUj7i1qMWSR83H3PZpw1h+21wAr1qxqF/8zgTVHS+sHTsu1zvepQDoDJN0Kv49quNJwWgAKDAK2xPy7jocg==" + }, + "node_modules/upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true, + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz", + "integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/update-browserslist-db/node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", + "deprecated": "Please see https://github.com/lydell/urix#deprecated" + }, + "node_modules/use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha512-aggiKfEEubv3UwRNqTzLInZpAOmKzwdHqEBmW/hBA/mt99eg+b4VrX6i+IRLxU8+WJYfa33rGwRseg4eElUgsQ==", + "bin": { + "user-home": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha512-jdBB2FrWvQC/pnPtIqcLsMaQgjhdb6B7tk1MMyTKapox+tQZbdRP4uLxu/JY0t7fbfDCUMnuelzEYv5GsxHhdg==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", + "dev": true, + "dependencies": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-2.0.0.tgz", + "integrity": "sha512-44i5QVLwRPbiRyuiHJ+zJXooNNRXUUifdfYIC1Gm7YTlemMgYQrZ+q1LERS6AYAN8w0xe7n9OgjEYckQjR5+4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "pify": "^2.3.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0", + "strip-bom-stream": "^2.0.0", + "vinyl": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vinyl-file/node_modules/clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha512-dhUqc57gSMCo6TX85FLfe51eC/s+Im2MLkAgJwfaRRexR2tA4dd3eLEW4L6efzHc2iNorrRRXITifnDLlRrhaA==", + "dev": true + }, + "node_modules/vinyl-file/node_modules/replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha512-AFBWBy9EVRTa/LhEcG8QDP3FvpwZqmvN2QFDuJswFeaVhWnZMp8q3E6Zd90SR04PlIwfGdyVjNyLPyen/ek5CQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/vinyl-file/node_modules/vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha512-Ci3wnR2uuSAWFMSglZuB8Z2apBdtOyz8CV7dC6/U1XbltXBC+IuutUkXQISz01P+US2ouBuesSbV6zILZ6BuzQ==", + "dev": true, + "dependencies": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + }, + "engines": { + "node": ">= 0.9" + } + }, + "node_modules/vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "dependencies": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-fs/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha512-NiibMgt6VJGJmyw7vtzhctDcfKch4e4n9TBeoWlirb7FMg9/1Ov9k+A5ZRAtywBpRPiyECvQRQllYM8dECegVA==", + "dev": true, + "dependencies": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-sourcemap/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha512-+oDh3KYZBoZC8hfocrbrxbLUeaYtQK7J5WU5Br9VqWqmCll3tFJqKp97GC9GmMsVIL0qnx2DgEDVxdo5EZ5sSw==", + "dev": true, + "dependencies": { + "source-map": "^0.5.1" + } + }, + "node_modules/vinyl-sourcemaps-apply/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vinyl/node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/vinyl/node_modules/replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "optional": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ==", + "dev": true + }, + "node_modules/winston": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.6.tgz", + "integrity": "sha512-J5Zu4p0tojLde8mIOyDSsmLmcP8I3Z6wtwpTDHx1+hGcdhxcJaAmG4CFtagkb+NiN1M9Ek4b42pzMWqfc9jm8w==", + "dependencies": { + "async": "^3.2.3", + "colors": "1.0.x", + "cycle": "1.0.x", + "eyes": "0.1.x", + "isstream": "0.1.x", + "stack-trace": "0.0.x" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==", + "dev": true, + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/xmlcreate": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", + "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", + "dev": true + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", + "dev": true + }, + "node_modules/yargs": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", + "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", + "dev": true, + "dependencies": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.1" + } + }, + "node_modules/yargs-parser": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", + "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", + "dev": true, + "dependencies": { + "camelcase": "^3.0.0", + "object.assign": "^4.1.0" + } + } + }, + "dependencies": { + "@babel/parser": { + "version": "7.18.11", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.11.tgz", + "integrity": "sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==", + "dev": true + }, + "@types/linkify-it": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", + "integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==", + "dev": true + }, + "@types/markdown-it": { + "version": "12.2.3", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", + "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", + "dev": true, + "requires": { + "@types/linkify-it": "*", + "@types/mdurl": "*" + } + }, + "@types/mdurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", + "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", + "dev": true + }, + "ansi-colors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "requires": { + "ansi-wrap": "^0.1.0" + } + }, + "ansi-cyan": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz", + "integrity": "sha512-eCjan3AVo/SxZ0/MyIYRtkpxIu/H3xZN7URr1vXVrISxeyz8fUFz0FJziamK4sS8I+t35y4rHg1b2PklyBe/7A==", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha512-HrgGIZUl8h2EHuZaU9hTR/cU5nhKxpVE1V6kdGsQ8e4zirElJ5fvtfc8N7Q1oq1aatO275i8pUFUCpNWCAnVWw==", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-red": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "integrity": "sha512-ewaIr5y+9CUTGFwZfpECUbFlGcC0GCw1oqR9RI6h1gQCd9Aj2GxSckCnPsVJnmfMZbwFYE+leZGASgkWl06Jow==", + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha512-ZyznvL8k/FZeQHr2T6LzcJ/+vBApDnMNZvfVFy3At0knswWd6rJ3/0Hhmpu8oqa6C92npmozs890sX9Dl6q+Qw==" + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha512-WLbYiXzD3y/ATLZFufV/rZvWdZOs+Z/+5v1rBZ463Jn398pa6kcde27cvozYnBoxXblGZTFfoPpsaEw0orU5BA==", + "dev": true, + "requires": { + "buffer-equal": "^1.0.0" + } + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==" + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==" + }, + "arr-filter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", + "integrity": "sha512-A2BETWCqhsecSvCkWAeVBFLH6sXEUGASuzkpjL3GR1SlL/PWL6M3J8EAAld2Uubmh39tvkJTqC9LeLHCUKmFXA==", + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", + "integrity": "sha512-tVqVTHt+Q5Xb09qRkbu+DidW1yYzz5izWS2Xm2yFm7qJnmUfz4HPzNxbHkdRJbz2lrqI7S+z17xNYdFcBBO8Hw==", + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==" + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha512-LeZY+DZDRnvP7eMuQ6LHfCzUGxAAIViUBliK24P3hWXL6y4SortgR6Nim6xrkfSLlmH0+k+9NYNwVC2s53ZrYQ==" + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA==" + }, + "array-initial": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", + "integrity": "sha512-BC4Yl89vneCYfpLrs5JU2aAu9/a+xWbeKhvISg9PT7eWFB9UlRvI+rKEtk6mgxWr3dSkk9gQ8hCrdqt06NXPdw==", + "dev": true, + "requires": { + "array-slice": "^1.0.0", + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "array-last": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", + "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", + "dev": true, + "requires": { + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==" + }, + "array-sort": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", + "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", + "dev": true, + "requires": { + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==" + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==" + }, + "async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "async-done": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz", + "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^2.0.0", + "stream-exhaust": "^1.0.1" + } + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "async-settle": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha512-VPXfB4Vk49z1LHHodrEQ6Xf7W4gg1w0dAPROHngx7qgDjqmIQ+fXmwgGXTW/ITLai0YLSvWepJOP9EVpMnEAcw==", + "dev": true, + "requires": { + "async-done": "^1.2.2" + } + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + }, + "autoprefixer": { + "version": "9.8.8", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.8.tgz", + "integrity": "sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==", + "dev": true, + "requires": { + "browserslist": "^4.12.0", + "caniuse-lite": "^1.0.30001109", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "picocolors": "^0.2.1", + "postcss": "^7.0.32", + "postcss-value-parser": "^4.1.0" + } + }, + "bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha512-bZOOfCb3gXBXbTFXq3OZtGR88LwGeJvzu6szttaIzymOTS4ZttBNOWSv7aLZja2EMycKtRYV0Oa8SNKH/zkxvg==", + "dev": true, + "requires": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "requires": { + "is-descriptor": "^1.0.0" + } + } + } + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha512-3vqtKL1N45I5dV0RdssXZG7X6pCqQrWPNOlBPZPrd+QkE2HEhR57Z04m0KtpbsZH73j+a3F8UD1TQnn+ExTvIA==" + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "bowser": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-1.9.4.tgz", + "integrity": "sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ==" + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + } + }, + "browserslist": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", + "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001370", + "electron-to-chromium": "^1.4.202", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.5" + } + }, + "buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha512-tcBWO2Dl4e7Asr9hTGcpVrCe+F7DubpmqWCTbj4FHLmjqO2hIaC383acQubWtRJhdceqs5uBHs6Es+Sk//RKiQ==", + "dev": true + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001378", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001378.tgz", + "integrity": "sha512-JVQnfoO7FK7WvU4ZkBRbPjaot4+YqxogSDosHv0Hv5mWpUESmN+UubMU6L/hGz8QlQ2aY5U0vR6MOs6j/CXpNA==", + "dev": true + }, + "catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chalkline": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/chalkline/-/chalkline-0.0.5.tgz", + "integrity": "sha512-FYfZecaZ6+eG2AVBzKmi5x1WgqRo7491HZ9VfJztMMkGFYQDEh4h4dBUJV1TUbUoix1tWUD/0QDSdu3SW3SXIg==", + "requires": { + "ansi-styles": "^2.1.0", + "chalk": "^1.1.1", + "escape-string-regexp": "^1.0.3" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==" + } + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + } + } + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha512-0yayqDxWQbqk3ojkYqUKqaAQ6AfNKeKWRNA8kR0WXzAsdHpP4BIaOmMAG87JGuO6qcobyW4GjxHd9PmhEd+T9w==", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==" + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha512-KLLTJWrvwIP+OPfMn0x2PheDEP20RPUcGXj/ERegTgdmPEZylALQldygiqrPPu8P45uNuPs7ckmReLY6v/iA5g==", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag==", + "dev": true + }, + "cloneable-readable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", + "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "dev": true + }, + "coffeescript": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-2.7.0.tgz", + "integrity": "sha512-hzWp6TUE2d/jCcN67LrW1eh5b/rSDKQK6oD6VMLlggYVUUFexgTH9z3dNYihzX4RMhze5FTUsUmOXViJKFQR/A==", + "dev": true + }, + "collection-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", + "integrity": "sha512-5D2XXSpkOnleOI21TG7p3T0bGAsZ/XknZpKBmGYyluO8pw4zA3K8ZlrBIbC4FXg3m6z/RNFiUFfT2sQK01+UHA==", + "dev": true, + "requires": { + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==", + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" + }, + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==" + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" + }, + "composer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/composer/-/composer-4.1.0.tgz", + "integrity": "sha512-qIIoNYjwFHrQFUdB8kD3pZs30+JeYK9149EpOYr/NVrii00KMO31IonzZMeRSU4qazyWZpEgVzkBmQ6VFWxedA==", + "requires": { + "pretty-time": "^1.1.0", + "use": "^3.1.1" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "concat-with-sourcemaps": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", + "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", + "dev": true, + "requires": { + "source-map": "^0.6.1" + } + }, + "convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==" + }, + "copy-props": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.5.tgz", + "integrity": "sha512-XBlx8HSqrT0ObQwmSzM7WE5k8FxTV75h1DX1Z3n6NhQ/UYYAvInWYmG06vFt7hQZArE2fuO62aihiWIVQwh1sw==", + "dev": true, + "requires": { + "each-props": "^1.3.2", + "is-plain-object": "^5.0.0" + } + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "cycle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "integrity": "sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA==" + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dev": true, + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "dateformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha512-GODcnWq3YGoTnygPfi02ygEiRxqUxpJwuRHjdhJYuxpcZmDq4rjBiXYmbCCzStxo176ixfLT6i4NPwQooRySnw==" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==" + }, + "default-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", + "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", + "dev": true, + "requires": { + "kind-of": "^5.0.2" + } + }, + "default-resolution": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", + "integrity": "sha512-2xaP6GiwVwOEbXCGoJ4ufgC76m8cj805jrghScewJC2ZDsb9U0b4BIrba+xt/Uytyd0HvQ6+WymSRTfnYj59GQ==", + "dev": true + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==", + "requires": { + "clone": "^1.0.2" + } + }, + "define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dev": true, + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + } + }, + "deprecated": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", + "integrity": "sha512-BRACtc6B1mJe2J2mruHFqHWrtLy0Qppu/7LKdqWH3o/9j1L/1phPUaQV+2S3H8ZDW0k6h+NEOKcHBDRikWLiOA==" + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==" + }, + "detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha512-+AWBwjGadtksxjOQSFDhPNQbed7icNXApT4+2BNpsXzcCBiInq2H9XW0O8sfHFaPmnQRs7cg/P0fAr2IWQSW0g==", + "requires": { + "readable-stream": "~1.1.9" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" + } + } + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "each-props": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", + "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" + }, + "dependencies": { + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + } + } + }, + "easy-table": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/easy-table/-/easy-table-1.2.0.tgz", + "integrity": "sha512-OFzVOv03YpvtcWGe5AayU5G2hgybsg3iqA6drU8UaoZyB9jLGMTrz9+asnLp/E+6qPh88yEI1gvyZFZ41dmgww==", + "requires": { + "ansi-regex": "^5.0.1", + "wcwidth": "^1.0.1" + } + }, + "electron-to-chromium": { + "version": "1.4.225", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.225.tgz", + "integrity": "sha512-ICHvGaCIQR3P88uK8aRtx8gmejbVJyC6bB4LEC3anzBrIzdzC7aiZHY4iFfXhN4st6I7lMO0x4sgBHf/7kBvRw==", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "dev": true + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es5-ext": { + "version": "0.10.62", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", + "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", + "dev": true, + "requires": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dev": true, + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + } + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha512-AFASGfIlnIbkKPQwX1yHaDjFvh/1gyKJODme52V6IORh69uEYgZp0o9C+qsIGNVEiuuhQU0CSSl++Rlegg1qvA==", + "dev": true, + "requires": { + "fill-range": "^2.1.0" + }, + "dependencies": { + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true, + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha512-QUzH43Gfb9+5yckcrSA0VBDwEtDUchrk4F6tfJZQuNzDJbEDB9cZNzSfXGQ1jqmdDY/kl41lUOWM9syA8z8jlg==", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "ext": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", + "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", + "dev": true, + "requires": { + "type": "^2.5.0" + }, + "dependencies": { + "type": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "requires": { + "is-descriptor": "^1.0.0" + } + } + } + }, + "eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==" + }, + "fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "requires": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" + } + }, + "fast-levenshtein": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz", + "integrity": "sha512-Ia0sQNrMPXXkqVFt6w6M1n1oKo3NfKs+mvaV811Jwir7vAk9a6PVV9VPYf6X3BU97QiLEmuW3uXH9u87zDFfdw==", + "dev": true + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha512-BTCqyBaWBTsauvnHiE8i562+EdJj+oUpkqWp2R1iCoR8f6oo8STRu3of7WJJ0TqWtxN50a5YFpzYK4Jj9esYfQ==", + "dev": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + } + }, + "find-index": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", + "integrity": "sha512-uJ5vWrfBKMcE6y2Z8834dwEZj9mNGxYa3t3I53OwFeuZ8D9oc2E5zcsrkuhX6h4iYrjhiv0T3szQmxlAV9uxDg==" + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + } + } + }, + "findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + }, + "dependencies": { + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + } + } + } + }, + "first-chunk-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz", + "integrity": "sha512-X8Z+b/0L4lToKYq+lwnKqi9X/Zek0NibLpsJgVsSxpoYq7JtiCtRb5HqKVEjEw/qAb/4AKKRLOwwKHlWNpm2Eg==", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } + }, + "flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==" + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==" + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==", + "requires": { + "for-in": "^1.0.1" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", + "requires": { + "map-cache": "^0.2.2" + } + }, + "fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" + }, + "dependencies": { + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "gaze": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", + "integrity": "sha512-3IWbXGkDDHFX8zIlNdfnmhvlSMhpBO6tDr4InB8fGku6dh/gjFPGNqcdsXJajZg05x9jRzXbL6gCnCnuMap4tw==", + "requires": { + "globule": "~0.1.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "get-intrinsic": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", + "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==" + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha512-ab1S1g1EbO7YzauaJLkgLp7DZVAqj9M/dvKlTt8DkXA2tiOIcSMrlVI2J1RZyB5iJVccEscjGn+kpOG9788MHA==", + "dev": true, + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + }, + "dependencies": { + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha512-JDYOvfxio/t42HKdxkAYaCiBN7oYiuxykOxKxdaUW5Qn0zaYN3gRQWolrwdnf0shM9/EP0ebuuTmyoXNr1cC5w==", + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha512-uMbLGAP3S2aDOHUDfdoYcdIePUCfysbAd0IAoWVZbeGU/oNQ8asHVSshLDJUPWxfzj8zsCG7/XeHPHTtow0nsw==", + "dev": true, + "requires": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + } + }, + "glob-watcher": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz", + "integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "normalize-path": "^3.0.0", + "object.defaults": "^1.1.0" + } + }, + "glob2base": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "integrity": "sha512-ZyqlgowMbfj2NPjxaZZ/EtsXlOch28FRXgMd64vqZWk1bT9+wvSRLYD1om9M7QfQru51zJPAT17qXm4/zd+9QA==", + "requires": { + "find-index": "^0.1.1" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "globule": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "integrity": "sha512-3eIcA2OjPCm4VvwIwZPzIxCVssA8HSpM2C6c6kK5ufJH4FGwWoyqL3In19uuX4oe+TwH3w2P1nQDmW56iehO4A==", + "requires": { + "glob": "~3.1.21", + "lodash": "~1.0.1", + "minimatch": "~0.2.11" + }, + "dependencies": { + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha512-ANhy2V2+tFpRajE3wN4DhkNQ08KDr0Ir1qL12/cUe5+a7STEK8jkW4onUYuY8/06qAFuT5je7mjAqzx0eKI2tQ==", + "requires": { + "graceful-fs": "~1.2.0", + "inherits": "1", + "minimatch": "~0.2.11" + } + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha512-iiTUZ5vZ+2ZV+h71XAgwCSu6+NAizhFU3Yw8aC/hH5SQ3SnISqEqAek40imAFGtDcwJKNhXvSY+hzIolnLwcdQ==" + }, + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha512-Al67oatbRSo3RV5hRqIoln6Y5yMVbJSIn4jEJNL7VCImzq/kLr7vvb6sFRJXqr8rpHc/2kJOM+y0sPKN47VdzA==" + }, + "lodash": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "integrity": "sha512-0VSEDVec/Me2eATuoiQd8IjyBMMX0fahob8YJ96V1go2RjvCk1m1GxmtfXn8RNSaLaTtop7fsuhhu9oLk3hUgA==" + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha512-zZ+Jy8lVWlvqqeM8iZB7w7KmQkoJn8djM585z88rywrEbzoqawVa9FR5p2hwD+y74nfuKOjmNvi9gtWJNLqHvA==", + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + } + } + }, + "glogg": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", + "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", + "requires": { + "sparkles": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "growly": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", + "integrity": "sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw==" + }, + "gulp": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz", + "integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==", + "dev": true, + "requires": { + "glob-watcher": "^5.0.3", + "gulp-cli": "^2.2.0", + "undertaker": "^1.2.1", + "vinyl-fs": "^3.0.0" + } + }, + "gulp-autoprefixer": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/gulp-autoprefixer/-/gulp-autoprefixer-6.1.0.tgz", + "integrity": "sha512-Ti/BUFe+ekhbDJfspZIMiOsOvw51KhI9EncsDfK7NaxjqRm+v4xS9v99kPxEoiDavpWqQWvG8Y6xT1mMlB3aXA==", + "dev": true, + "requires": { + "autoprefixer": "^9.5.1", + "fancy-log": "^1.3.2", + "plugin-error": "^1.0.1", + "postcss": "^7.0.2", + "through2": "^3.0.1", + "vinyl-sourcemaps-apply": "^0.2.1" + } + }, + "gulp-cli": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz", + "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "archy": "^1.0.0", + "array-sort": "^1.0.0", + "color-support": "^1.1.3", + "concat-stream": "^1.6.0", + "copy-props": "^2.0.1", + "fancy-log": "^1.3.2", + "gulplog": "^1.0.0", + "interpret": "^1.4.0", + "isobject": "^3.0.1", + "liftoff": "^3.1.0", + "matchdep": "^2.0.0", + "mute-stdout": "^1.0.0", + "pretty-hrtime": "^1.0.0", + "replace-homedir": "^1.0.0", + "semver-greatest-satisfied-range": "^1.1.0", + "v8flags": "^3.2.0", + "yargs": "^7.1.0" + } + }, + "gulp-concat": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", + "integrity": "sha512-a2scActrQrDBpBbR3WUZGyGS1JEPLg5PZJdIa7/Bi3GuKAmPYDK6SFhy/NZq5R8KsKKFvtfR0fakbUCcKGCCjg==", + "dev": true, + "requires": { + "concat-with-sourcemaps": "^1.0.0", + "through2": "^2.0.0", + "vinyl": "^2.0.0" + }, + "dependencies": { + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, + "gulp-line-ending-corrector": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/gulp-line-ending-corrector/-/gulp-line-ending-corrector-1.0.3.tgz", + "integrity": "sha512-l68bon1Bbni5S5boKqya3MiwDGn8f6XGV7fsmOokkS+etVk/LY+OhFm24xy0Jlo8Xf0Rx4LsDNhmdzUGIaw7Yg==", + "dev": true, + "requires": { + "coffeescript": "^2.0.3", + "line-ending-corrector": "^1.0.1", + "plugin-error": "^1.0.1", + "through2": "^2.0.0" + }, + "dependencies": { + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, + "gulp-messenger": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/gulp-messenger/-/gulp-messenger-0.28.2.tgz", + "integrity": "sha512-QXzzeLFDs1WazQT5eWVvdl7XpMhj9f/WXxouI8sqSdplXoe8GPJXSpRGcqRY4Xcfc7ecdIWo1GVgZLLvDUczIw==", + "requires": { + "ansi-styles": "3.0.0", + "bowser": "^1.6.0", + "chalk": "^2.0.1", + "chalkline": "0.0.5", + "defaults": "1.0.3", + "detect-node": "^2.0.3", + "easy-table": "^1.0.0", + "gulp": "3.9.1", + "is_js": "^0.9.0", + "lodash": "^3.10.1", + "lodash-deep": "^1.6.0", + "lodash._getnative": "^3.9.1", + "lodash.isarguments": "^3.1.0", + "lodash.isarray": "^4.0.0", + "mkdirp": "^0.5.1", + "moment": "^2.17.1", + "path-exists": "3.0.0", + "pretty-hrtime": "^1.0.3", + "purdy": "^2.2.0", + "sprintf-js": "1.0.3", + "through2": "^2.0.3", + "up": "^1.0.2", + "winston": "^2.3.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "ansi-styles": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.0.0.tgz", + "integrity": "sha512-caosO5GROQ6HZCO0PCuqFmKb0g2ow+7fvz60N3/A3ggyeDnFvLjW8mLR84eK/6hsh206bSm3s3j34bLKJPcnLw==", + "requires": { + "color-convert": "^1.0.0" + } + }, + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha512-g62n3Kb9cszeZvmvBUqP/dsEJD/+80pDA8u8KqHnAPrVnQ2Je9rVV6opxkhuWCd1kCn2gOibzDKxCtBvD3q5kA==" + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha512-dhUqc57gSMCo6TX85FLfe51eC/s+Im2MLkAgJwfaRRexR2tA4dd3eLEW4L6efzHc2iNorrRRXITifnDLlRrhaA==" + }, + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha512-vs+3unmJT45eczmcAZ6zMJtxN3l/QXeccaXQx5cu/MeJMhewVfoWZqibRkOxPnmoR59+Zy5hjabfQc6JLSah4g==", + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "first-chunk-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha512-ArRi5axuv66gEsyl3UuK80CzW7t56hem73YGNYxNWTGNKFJUadSb9Gu9SHijYEUi8ulQMf1bJomYNwSCPHhtTQ==" + }, + "glob": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha512-I0rTWUKSZKxPSIAIaqhSXTM/DiII6wame+rEC3cFA5Lqmr9YmdL7z6Hj9+bdWtTvoY1Su4/OiMLmb37Y7JzvJQ==", + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^2.0.1", + "once": "^1.3.0" + } + }, + "glob-stream": { + "version": "3.1.18", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "integrity": "sha512-owHtlMMXIAbxLjhUAO0HhW1/TB7kV0AwDduI3BLbYsWCaRzNIcLBu8N0wHZft2Za2SCmUXCEOdpZzC7k/H19eg==", + "requires": { + "glob": "^4.3.1", + "glob2base": "^0.0.12", + "minimatch": "^2.0.1", + "ordered-read-streams": "^0.1.0", + "through2": "^0.6.1", + "unique-stream": "^1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha512-RkK/CCESdTKQZHdmKICijdKKsCRVHs5KsLZ6pACAmF/1GPUQhonHSXWNERctxEp7RmvjdNbZTL5z9V7nSCXKcg==", + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + } + } + }, + "glob-watcher": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "integrity": "sha512-lzYWq1BJLBmtb9rzT6+lgbFlEW6Sc7B+Qs3RmsNA9lbdFSqLHhebfypPR3nbEOMeEQyawVXqSDH0aqjtImldow==", + "requires": { + "gaze": "^0.5.1" + } + }, + "graceful-fs": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.12.tgz", + "integrity": "sha512-J55gaCS4iTTJfTXIxSVw3EMQckcqkpdRv3IR7gu6sq0+tbC363Zx6KH/SEwXASK9JRbhyZmVjJEVJIOxYsB3Qg==", + "requires": { + "natives": "^1.1.3" + } + }, + "gulp": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", + "integrity": "sha512-6FHNdR+VG1LcPz6gZGGqgvimWWGtl4x3FvshAdK/UnAjU7aFOyzft3Fjp35r0Y3ZF4u8vND0S4nGsIB/sxTqzQ==", + "requires": { + "archy": "^1.0.0", + "chalk": "^1.0.0", + "deprecated": "^0.0.1", + "gulp-util": "^3.0.0", + "interpret": "^1.0.0", + "liftoff": "^2.1.0", + "minimist": "^1.1.0", + "orchestrator": "^0.3.0", + "pretty-hrtime": "^1.0.0", + "semver": "^4.1.0", + "tildify": "^1.0.0", + "v8flags": "^2.0.2", + "vinyl-fs": "^0.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + } + } + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "requires": { + "is-extglob": "^2.1.0" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "liftoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", + "integrity": "sha512-01zfGFqfORP1CGmZZP2Zn51zsqz4RltDi0RDOhbGoLYdUT5Lw+I2gX6QdwXhPITF6hPOHEOp+At6/L24hIg9WQ==", + "requires": { + "extend": "^3.0.0", + "findup-sync": "^2.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + } + }, + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha512-9mDDwqVIma6OZX79ZlDACZl8sBm0TEnkf99zV3iMA4GzkIT/9hiqP5mY0HoT1iNLCrKc/R1HByV+yJfRWVJryQ==" + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha512-jQo6o1qSVLEWaw3l+bwYA2X0uLuK2KjNh2wjgO7Q/9UJnXr1Q3yQKR8BI0/Bt/rPg75e6SMW4hW/6cBHVTZUjA==", + "requires": { + "brace-expansion": "^1.0.0" + } + }, + "ordered-read-streams": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "integrity": "sha512-PMX5ehiNri4+lgk9fl09xuPeciGmyPyVUSBwwPT4C/3EHGxoVf7UdgKDE3SLBD4pUDmlzrg1L1cK5igrp+Tyuw==" + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha512-IrpJ+yoG4EOH8DFWuVg+8H1kW1Oaof0Wxe7cPcXW3x9BjkN/eVo54F15LyqemnDIUYskQWr9qvl/RihmSy6+xQ==" + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "integrity": "sha512-qVAeAIjblKDp/8Cd0tJdxpe3Iq/HooI7En98alEaMbz4Wedlrcj3WI72dDQSrziRW5IQ0zeBo3JXsmS8RcS9jg==", + "requires": { + "first-chunk-stream": "^1.0.0", + "is-utf8": "^0.2.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==" + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "unique-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", + "integrity": "sha512-L8KM6TdpsoBk6TJTXevbmpub3bATS06Znu3BcfVPVQkFtnh1MFeCZ3gFKCQcji7f7YYiigsO5OR99vqhoNT8nQ==" + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha512-SKfhk/LlaXzvtowJabLZwD4K6SGRYeoxA7KJeISlUMAB/NT4CBkZjMq3WceX2Ckm4llwqYVo8TICgsDYCBU2tA==", + "requires": { + "user-home": "^1.1.1" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha512-pmza4M5VA15HOImIQYWhoXGlGNafCm0QK5BpBUXkzzEwrRxKqBsbAhTfkT2zMcJhUX1G1Gkid0xaV8WjOl7DsA==", + "requires": { + "clone": "^0.2.0", + "clone-stats": "^0.0.1" + } + }, + "vinyl-fs": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", + "integrity": "sha512-9CTKjt8378nhdydwFDTwywKio0n8aqq6xA70g0uypcnTNSCow/gQOwv0L9E2GaKd7EQ3kZl/diBxPSCgcBXESw==", + "requires": { + "defaults": "^1.0.0", + "glob-stream": "^3.1.5", + "glob-watcher": "^0.0.6", + "graceful-fs": "^3.0.0", + "mkdirp": "^0.5.0", + "strip-bom": "^1.0.0", + "through2": "^0.6.1", + "vinyl": "^0.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha512-RkK/CCESdTKQZHdmKICijdKKsCRVHs5KsLZ6pACAmF/1GPUQhonHSXWNERctxEp7RmvjdNbZTL5z9V7nSCXKcg==", + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + } + } + } + } + }, + "gulp-notify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/gulp-notify/-/gulp-notify-3.0.0.tgz", + "integrity": "sha512-xMK/3J7rOF9+97NMCzuZmgYx0xCmwswaCKMSdIU/2VV4GzuZGexY0CtFtN/zR4+OmAHy5Zx2w8FGn89Xk90UUw==", + "requires": { + "gulp-util": "^3.0.8", + "lodash.template": "^4.4.0", + "node-notifier": "^5.0.1", + "node.extend": "^1.1.6", + "through2": "^2.0.3" + }, + "dependencies": { + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, + "gulp-phpunit": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/gulp-phpunit/-/gulp-phpunit-0.26.0.tgz", + "integrity": "sha512-px1/qpMpHjgdoKYCMmZAyXwquKxMMUU5OQCYDNYZxnnlTJKK79hU4CqR1Hhdb6/N9H05zcX3Fbnx2O4lsB0wMA==", + "requires": { + "chalk": "^2.0.1", + "chalkline": "0.0.5", + "gulp-messenger": "^0.28.2", + "gulp-notify": "3.0.0", + "lodash": "^4.15.0", + "map-stream": "~0.0.4", + "node-notifier": "5.0.2", + "plugin-error": "^0.1.2", + "shelljs": "0.7.6" + }, + "dependencies": { + "arr-diff": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha512-OQwDZUqYaQwyyhDJHThmzId8daf4/RFNLaeh3AevmSeZ5Y7ug4Ga/yKc6l6kTZOBW781rCj103ZuTh8GAsB3+Q==", + "requires": { + "arr-flatten": "^1.0.1", + "array-slice": "^0.2.3" + } + }, + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha512-t5db90jq+qdgk8aFnxEkjqta0B/GHrM1pxzuuZz2zWsOXc5nKu3t+76s/PQBA8FTcM/ipspIH9jWG4OxCBc2eA==" + }, + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha512-rlVfZW/1Ph2SNySXwR9QYkChp8EkOEiTMO5Vwx60usw04i4nWemkm9RXmQqgkQFaLHsqLuADvjp6IfgL9l2M8Q==" + }, + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha512-L7AGmkO6jhDkEBBGWlLtftA80Xq8DipnrRPr0pyi7GQLXkaq9JYA4xF4z6qnadIC6euiTDKco0cGSU9muw+WTw==", + "requires": { + "kind-of": "^1.1.0" + } + }, + "kind-of": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha512-aUH6ElPnMGon2/YkxRIigV32MOpTVcoXQ1Oo8aYn40s+sJ3j+0gFZsT8HKDcxNy7Fi9zuquWtGaGAahOdv5p/g==" + }, + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha512-WzZHcm4+GO34sjFMxQMqZbsz3xiNEgonCskQ9v+IroMmYgk/tas8dG+Hr2D6IbRPybZ12oWpzE/w3cGJ6FJzOw==", + "requires": { + "ansi-cyan": "^0.1.1", + "ansi-red": "^0.1.1", + "arr-diff": "^1.0.1", + "arr-union": "^2.0.1", + "extend-shallow": "^1.1.2" + } + } + } + }, + "gulp-rename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-2.0.0.tgz", + "integrity": "sha512-97Vba4KBzbYmR5VBs9mWmK+HwIf5mj+/zioxfZhOKeXtx5ZjBk57KFlePf5nxq9QsTtFl0ejnHE3zTC9MHXqyQ==", + "dev": true + }, + "gulp-sass": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/gulp-sass/-/gulp-sass-5.1.0.tgz", + "integrity": "sha512-7VT0uaF+VZCmkNBglfe1b34bxn/AfcssquLKVDYnCDJ3xNBaW7cUuI3p3BQmoKcoKFrs9jdzUxyb+u+NGfL4OQ==", + "dev": true, + "requires": { + "lodash.clonedeep": "^4.5.0", + "picocolors": "^1.0.0", + "plugin-error": "^1.0.1", + "replace-ext": "^2.0.0", + "strip-ansi": "^6.0.1", + "vinyl-sourcemaps-apply": "^0.2.1" + }, + "dependencies": { + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + } + } + }, + "gulp-uglify": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.2.tgz", + "integrity": "sha512-gk1dhB74AkV2kzqPMQBLA3jPoIAPd/nlNzP2XMDSG8XZrqnlCiDGAqC+rZOumzFvB5zOphlFh6yr3lgcAb/OOg==", + "dev": true, + "requires": { + "array-each": "^1.0.1", + "extend-shallow": "^3.0.2", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "isobject": "^3.0.1", + "make-error-cause": "^1.1.1", + "safe-buffer": "^5.1.2", + "through2": "^2.0.0", + "uglify-js": "^3.0.5", + "vinyl-sourcemaps-apply": "^0.2.0" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha512-q5oWPc12lwSFS9h/4VIjG+1NuNDlJ48ywV2JKItY4Ycc/n1fXJeYPVQsfu5ZrhQi7FGSDBalwUCLar/GyHXKGw==", + "requires": { + "array-differ": "^1.0.0", + "array-uniq": "^1.0.2", + "beeper": "^1.0.0", + "chalk": "^1.0.0", + "dateformat": "^2.0.0", + "fancy-log": "^1.1.0", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "lodash._reescape": "^3.0.0", + "lodash._reevaluate": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.template": "^3.0.0", + "minimist": "^1.1.0", + "multipipe": "^0.1.2", + "object-assign": "^3.0.0", + "replace-ext": "0.0.1", + "through2": "^2.0.0", + "vinyl": "^0.5.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha512-dhUqc57gSMCo6TX85FLfe51eC/s+Im2MLkAgJwfaRRexR2tA4dd3eLEW4L6efzHc2iNorrRRXITifnDLlRrhaA==" + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha512-0B4Y53I0OgHUJkt+7RmlDFWKjVAI/YUpWNiL9GQz5ORDr4ttgfQGo+phBWKFLJbBdtOwgMuUkdOHOnPg45jKmQ==", + "requires": { + "lodash._basecopy": "^3.0.0", + "lodash._basetostring": "^3.0.0", + "lodash._basevalues": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0", + "lodash.keys": "^3.0.0", + "lodash.restparam": "^3.0.0", + "lodash.templatesettings": "^3.0.0" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha512-TcrlEr31tDYnWkHFWDCV3dHYroKEXpJZ2YJYvJdhN+y4AkWMDZ5I4I8XDtUKqSAyG81N7w+I1mFEJtcED+tGqQ==", + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" + } + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha512-AFBWBy9EVRTa/LhEcG8QDP3FvpwZqmvN2QFDuJswFeaVhWnZMp8q3E6Zd90SR04PlIwfGdyVjNyLPyen/ek5CQ==" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==" + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha512-P5zdf3WB9uzr7IFoVQ2wZTmUwHL8cMZWJGzLBNCHNZ3NB6HTMsYABtt7z8tAGIINLXyAob9B9a1yzVGMFOYKEA==", + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "gulp-watch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/gulp-watch/-/gulp-watch-5.0.1.tgz", + "integrity": "sha512-HnTSBdzAOFIT4wmXYPDUn783TaYAq9bpaN05vuZNP5eni3z3aRx0NAKbjhhMYtcq76x4R1wf4oORDGdlrEjuog==", + "dev": true, + "requires": { + "ansi-colors": "1.1.0", + "anymatch": "^1.3.0", + "chokidar": "^2.0.0", + "fancy-log": "1.3.2", + "glob-parent": "^3.0.1", + "object-assign": "^4.1.0", + "path-is-absolute": "^1.0.1", + "plugin-error": "1.0.1", + "readable-stream": "^2.2.2", + "slash": "^1.0.0", + "vinyl": "^2.1.0", + "vinyl-file": "^2.0.0" + }, + "dependencies": { + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "requires": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha512-dtXTVMkh6VkEEA7OhXnN1Ecb8aAGFdZ1LFxtOCoqj4qkyOJMt7+qs6Ahdy6p/NQCPYsRSXXivhSB/J5E9jmYKA==", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha512-G2n5bG5fSUCpnsXz4+8FUkYsGPkNfLn9YvS66U5qbTIXI2Ynnlo4Bi42bWv+omKUCqz+ejzfClwne0alJWJPhg==", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha512-xU7bpz2ytJl1bH9cgIurjpg/n8Gohy9GTw81heDYLJQ4RU60dlyJsa+atVF2pI0yMMvKxI9HkKwjePCj5XI1hw==", + "dev": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha512-hxx03P2dJxss6ceIeri9cmYOT4SRs3Zk3afZwWpOsRqLqprhTR8u++SlC+sFGsQr7WGFPdMF7Gjc1njDLDK6UA==", + "dev": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha512-1FOj1LOwn42TMrruOHGt18HemVnbwAmAak7krWk+wa93KXxGbK+2jpezm+ytJYDaBX0/SPLZFHKM7m+tKobWGg==", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "fancy-log": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha512-7E6IFy84FpO6jcnzEsCcoxDleHpMTFzncmCXXBIVYq1/Oakqnbc/lTKPJyyW6edGeC/rnZmV78hJe7SuoZo0aQ==", + "dev": true, + "requires": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "time-stamp": "^1.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha512-LnU2XFEk9xxSJ6rfgAry/ty5qwUTyHYOBU0g4R6tIw5ljwgGIBmiKhRWLw5NpMOnrgUNcDJ4WMp8rl3sYVHLNA==", + "dev": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha512-hm6N8nrm3Y08jXie48jsC55eCZz9mnb4OirAStEk2deqeyhXU3C1otDVh+ccttMuc1sBi6RX6ZJ720hs9RCvgw==", + "requires": { + "glogg": "^1.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==" + } + } + }, + "has-color": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", + "integrity": "sha512-kaNz5OTAYYmt646Hkqw50/qyxP2vFnTVu5AQ1Zmk22Kk5+4Qx6BpO8+u7IKsML5fOsFk0ZT0AcCJNYwcvaLBvw==" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha512-+F4GzLjwHNNDEAJW2DC1xXfEoPkRDmUdJ7CBYw4MpqtDwOnqdImJl7GWlpqx+Wko6//J8uKTnIe4wZSv7yCqmw==", + "requires": { + "sparkles": "^1.0.0" + } + }, + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==", + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==", + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha512-V6Yw1rIcYV/4JsnggjBU0l4Kr+EXhpwqXRusENU1Xx6ro00IHPHYNynCuBTOZAPlr3AAmLvchH9I7N/VUdvOwQ==" + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "immutable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz", + "integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ==", + "dev": true + }, + "is": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/is/-/is-3.3.0.tgz", + "integrity": "sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg==" + }, + "is_js": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/is_js/-/is_js-0.9.0.tgz", + "integrity": "sha512-8Y5EHSH+TonfUHX2g3pMJljdbGavg55q4jmHzghJCdqYDbdNROC8uw/YFQwIRCRqRJT1EY3pJefz+kglw+o7sg==" + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "requires": { + "kind-of": "^6.0.0" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-core-module": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "requires": { + "has": "^1.0.3" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "requires": { + "kind-of": "^6.0.0" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + } + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + } + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha512-9YclgOGtN/f8zx0Pr4FQYMdibBiTaH3sn52vjYip4ZSf6C4/6RfTEZ+MR4GvKhCxdPh21Bg42/WL55f6KSnKpg==", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha512-0EygVC5qPvIyb+gSz7zdD5/AAoS6Qrx1e//6N4yv4oNm30kqvdmG66oZFWVlQHUWe5OjP08FuTw2IdT0EOTcYA==", + "dev": true, + "requires": { + "is-primitive": "^2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha512-Yu68oeXJ7LeWNmZ3Zov/xg/oDBnBK2RNxwYY1ilNJX+tKKZqgPK+qOn/Gs9jEu66KDY9Netf5XLKNGzas/vPfQ==", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha512-N3w1tFaRfk3UrPfqeRyD+GYDASU3W5VinKhlORy8EWVf/sIdDL9GAcew85XmktCfH+ngG7SRXEVDoO18WMdB/Q==", + "dev": true + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "requires": { + "is-unc-path": "^1.0.0" + } + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "requires": { + "unc-path-regex": "^0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==" + }, + "is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA==", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "isemail": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz", + "integrity": "sha512-pZMb1rDrWRAPtVY92VCxWtF+1gExWrCnao+GL1EKHx6z19ovW+xNcnC1iNB7WkbSYWlyl3uwlaH5eaBx2s2crw==" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" + }, + "joi": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz", + "integrity": "sha512-K6+OwGaWM1sBEu+XMbgC4zDmg6hnddS2DWiCVtjnhkcrzv+ejSfh7HGUsoxmWQkv6kHEsVFAywttfkpmIE2QwQ==", + "requires": { + "hoek": "2.x.x", + "isemail": "1.x.x", + "moment": "2.x.x", + "topo": "1.x.x" + } + }, + "js2xmlparser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", + "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", + "dev": true, + "requires": { + "xmlcreate": "^2.0.4" + } + }, + "jsdoc": { + "version": "3.6.11", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.11.tgz", + "integrity": "sha512-8UCU0TYeIYD9KeLzEcAu2q8N/mx9O3phAGl32nmHlE0LpaJL71mMkP4d+QE5zWfNt50qheHtOZ0qoxVrsX5TUg==", + "dev": true, + "requires": { + "@babel/parser": "^7.9.4", + "@types/markdown-it": "^12.2.3", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^12.3.2", + "markdown-it-anchor": "^8.4.1", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "taffydb": "2.6.2", + "underscore": "~1.13.2" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + } + } + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "just-debounce": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.1.0.tgz", + "integrity": "sha512-qpcRocdkUmf+UTNBYx5w6dexX5J31AKK1OmPwH630a83DdVVUIngk55RSAiIGpQyoH0dlr872VHfPjnQnK1qDQ==", + "dev": true + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + }, + "klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.9" + } + }, + "last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha512-U/VxvpX4N/rFvPzr3qG5EtLKEnNI0emvIQB3/ecEwv+8GHaUKbIB8vxv1Oai5FAF0d0r7LXHhLLe5K/yChm5GQ==", + "dev": true, + "requires": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + } + }, + "lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw==", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha512-IpSVCk9AYvLHo5ctcIXxOBpMWUe+4TKN3VPWAKUbJikkmsGp0VrSM8IttVc32D6J4WUsiPE6aEFRNmIoF/gdow==", + "dev": true, + "requires": { + "flush-write-stream": "^1.0.2" + } + }, + "liftoff": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz", + "integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==", + "dev": true, + "requires": { + "extend": "^3.0.0", + "findup-sync": "^3.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + }, + "dependencies": { + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + } + } + }, + "line-ending-corrector": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/line-ending-corrector/-/line-ending-corrector-1.0.1.tgz", + "integrity": "sha512-uwHj4enSztzPuHdDCysaO94S2bNk8gfR2TKIzPYz2v3sDq/7L6aUxg4uZHnbDYFIdjjxhxcA/2YE7RCqpSbY+A==", + "dev": true, + "requires": { + "coffeescript": "^2.0.3" + } + }, + "linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "dev": true, + "requires": { + "uc.micro": "^1.0.1" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash-deep": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lodash-deep/-/lodash-deep-1.6.0.tgz", + "integrity": "sha512-KXP3vvDWAiZ3wDEcS9Hzgrk/hyaz9A2XfNsZULNmbNQwVG9eShQr4kPE70RNcxF+XSTDK9HmfSjg71BYVXBNog==", + "requires": { + "lodash": ">=2.4.1" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha512-rFR6Vpm4HeCK1WPGvjZSJ+7yik8d8PVUdCJx5rT2pogG4Ve/2ZS7kfmO5l5T2o5V2mqlNIfSF5MZlr1+xOoYQQ==" + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha512-mTzAr1aNAv/i7W43vOR/uD/aJ4ngbtsRaCubp2BfZhlGU/eORUjg/7F6X0orNMdv33JOrdgGybtvMN/po3EWrA==" + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha512-H94wl5P13uEqlCg7OcNNhMQ8KvWSIyqXzOPusRgHC9DK3o54P6P3xtbXlVbRABG4q5gSmp7EDdJ0MSuW9HX6Mg==" + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha512-RrL9VxMEPyDMHOd9uFbvMe8X55X16/cGM5IgOKgRElQZutpX89iS6vwl64duTV1/16w5JY7tuFNXqoekmh1EmA==" + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha512-De+ZbrMu6eThFti/CSzhRvTKMgQToLxbij58LMfM8JnYDNSOjkjTCIaa8ixglOeGh2nyPlakbt5bJWJ7gvpYlQ==" + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha512-Sjlavm5y+FUVIF3vF3B75GyXrzsfYV8Dlv3L4mEpuB9leg8N6yf/7rU06iLPx9fY0Mv3khVp9p7Dx0mGV6V5OQ==" + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha512-OrPwdDc65iJiBeUe5n/LIjd7Viy99bKwDdk7Z5ljfZg0uFRFlfQaCy9tZ4YMAag9WAZmlVpe1iZrkIMMSMHD3w==" + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==" + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha512-O0pWuFSK6x4EXhM1dhZ8gchNtG7JMqBtrHdoUFUWXD7dJnNSUze1GuyQr5sOs0aCvgGeI3o/OJW8f4ca7FDxmQ==" + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "dev": true + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha512-n1PZMXgaaDWZDSvuNZ/8XOcYO2hOKDqZel5adtR30VKQAtoWs/5AOeFA0vPV8moiPzlqe7F4cP2tzpFewQyelQ==", + "requires": { + "lodash._root": "^3.0.0" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==" + }, + "lodash.isarray": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-4.0.0.tgz", + "integrity": "sha512-V8ViWvoNlXpCrB6Ewaj3ScRXUpmCvqp4tJUxa3dlovuJj/8lp3SND5Kw4v5OeuHgoyw4qJN+gl36qZqp6WYQ6g==" + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha512-CuBsapFjcubOGMn3VD+24HOAPxM79tH+V6ivJL3CHYjtrawauDJHUk//Yew9Hvc6e9rbCrURGk8z6PC+8WJBfQ==", + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + }, + "dependencies": { + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha512-JwObCrNJuT0Nnbuecmqr5DgtuBppuCvGD9lxjFpAzwnVtdGoDQ1zig+5W8k5/6Gcn0gZ3936HDAlGd28i7sOGQ==" + } + } + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha512-L4/arjjuq4noiUJpt3yS6KIKDtJwNe2fIYgMqyYYKoeIfV1iEqvPwhCx23o+R9dzouGihDAPN1dTIRWa7zk8tw==" + }, + "lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "requires": { + "lodash._reinterpolate": "^3.0.0" + } + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha512-WpibWJ60c3AgAz8a2iYErDrcT2C7OmKnsWhIcHOjkUHFjkXncJhtLxNSqUmxRxRunpb5I8Vprd7aNSd2NtksJQ==" + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "make-error-cause": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", + "integrity": "sha512-4TO2Y3HkBnis4c0dxhAgD/jprySYLACf7nwN6V0HAHDx59g12WlRpUmFy1bRHamjGUEEBrEvCq6SUpsEE2lhUg==", + "dev": true, + "requires": { + "make-error": "^1.2.0" + } + }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "requires": { + "kind-of": "^6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + } + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==" + }, + "map-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", + "integrity": "sha512-C0X0KQmGm3N2ftbTGBhSyuydQ+vV1LC3f3zPvT3RXHXNZrvfPZcoXp/N5DOa8vedX/rTMm2CjTtivFg2STJMRQ==" + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==", + "requires": { + "object-visit": "^1.0.0" + } + }, + "markdown-it": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "dev": true, + "requires": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + } + }, + "markdown-it-anchor": { + "version": "8.6.4", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.4.tgz", + "integrity": "sha512-Ul4YVYZNxMJYALpKtu+ZRdrryYt/GlQ5CK+4l1bp/gWXOG2QWElt6AqF3Mih/wfUKdZbNAZVXGR73/n6U/8img==", + "dev": true, + "requires": {} + }, + "marked": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.18.tgz", + "integrity": "sha512-wbLDJ7Zh0sqA0Vdg6aqlbT+yPxqLblpAZh1mK2+AO2twQkPywvvqQNfEPVwSSRjZ7dZcdeVBIAgiO7MMp3Dszw==", + "dev": true + }, + "matchdep": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", + "integrity": "sha512-LFgVbaHIHMqCRuCZyfCtUOq9/Lnzhi7Z0KFUE2fhD54+JN2jLh3hC02RLkqauJ3U4soU6H1J3tfj/Byk7GoEjA==", + "dev": true, + "requires": { + "findup-sync": "^2.0.0", + "micromatch": "^3.0.4", + "resolve": "^1.4.0", + "stack-trace": "0.0.10" + }, + "dependencies": { + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha512-vs+3unmJT45eczmcAZ6zMJtxN3l/QXeccaXQx5cu/MeJMhewVfoWZqibRkOxPnmoR59+Zy5hjabfQc6JLSah4g==", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "math-random": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", + "dev": true + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + } + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + } + } + } + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "requires": { + "minimist": "^1.2.6" + } + }, + "moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha512-7ZxrUybYv9NonoXgwoOqtStIu18D1c3eFZj27hqgf5kBrBF8Q+tE8V0MW8dKM5QLkQPh1JhhbKgHLY9kifov4Q==", + "requires": { + "duplexer2": "0.0.2" + } + }, + "mute-stdout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", + "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", + "dev": true + }, + "nan": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.16.0.tgz", + "integrity": "sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + } + } + }, + "natives": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.6.tgz", + "integrity": "sha512-6+TDFewD4yxY14ptjKaS63GVdtKiES1pTPyxn9Jb0rBqPMZ7VcCiooEhPNsr+mqHtMGxa/5c/HhcC4uPEUw/nA==" + }, + "next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "dev": true + }, + "node-notifier": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.0.2.tgz", + "integrity": "sha512-nmc9wotRDRFGrV2zn6VmdkZjqr2dnzM23KRfMATDYt1XvlfjIqLf+THlXeO1+Wbltz04EeIO9FVVhBzQtVTZCg==", + "requires": { + "growly": "^1.3.0", + "semver": "^5.3.0", + "shellwords": "^0.1.0", + "which": "^1.2.12" + } + }, + "node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "dev": true + }, + "node.extend": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.8.tgz", + "integrity": "sha512-L/dvEBwyg3UowwqOUTyDsGBU6kjBQOpOhshio9V3i3BMPv5YUb9+mWNN8MK0IbWqT0AqaTSONZf0aTuMMahWgA==", + "requires": { + "has": "^1.0.3", + "is": "^3.2.1" + } + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true + }, + "now-and-later": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "dev": true, + "requires": { + "once": "^1.3.2" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg==", + "dev": true + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "dev": true + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha512-jHP15vXVGeVh1HuaA2wY6lxk+whK/x4KBG88VXeRma7CCun7iGD5qPc4eYykQ9sdQvg8jkwFKsSxHln2ybW3xQ==" + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==", + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==", + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==", + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha512-3+mAJu2PLfnSVGHwIWubpOFLscJANBKuB/6A4CxBstc4aqwQY0FWcsppuy4jU5GSB95yES5JHSI+33AWuS4k6w==", + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha512-UiAM5mhmIuKLsOvrL+B0U2d1hXHF3bFYWIuH1LMpuV2EJEHG1Ntz06PgLEHjm6VFd87NpH8rastvPoyv6UW2fA==", + "dev": true, + "requires": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + }, + "dependencies": { + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha512-SKmowqGTJoPzLO1T0BBJpkfp3EMacCMOuH40hOUbrbzElVktk4DioXVM99QkLCyKoiuOmyjgcWMpVz2xjE7LZw==", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + } + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", + "requires": { + "isobject": "^3.0.1" + } + }, + "object.reduce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", + "integrity": "sha512-naLhxxpUESbNkRqc35oQ2scZSJueHGQNUfMW/0U37IgN6tE2dgDWg3whf+NEliy3F/QysrO48XKUz/nGPe+AQw==", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "requires": { + "wrappy": "1" + } + }, + "orchestrator": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", + "integrity": "sha512-DrQ43ngaJ0e36j2CHyoDoIg1K4zbc78GnTQESebK9vu6hj4W5/pvfSFO/kgM620Yd0YnhseSNYsLK3/SszZ5NQ==", + "requires": { + "end-of-stream": "~0.1.5", + "sequencify": "~0.0.7", + "stream-consume": "~0.1.0" + }, + "dependencies": { + "end-of-stream": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "integrity": "sha512-go5TQkd0YRXYhX+Lc3UrXkoKU5j+m72jEP5lHWr2Nh82L8wfZtH8toKgcg4T10o23ELIMGXQdwCbl+qAXIPDrw==", + "requires": { + "once": "~1.3.0" + } + }, + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha512-6vaNInhu+CHxtONf3zw3vq4SP2DOQhjBvIa3rNcG0+P7eKWlYH6Peu7rHizSloRU2EwMz6GraLieis9Ac9+p1w==", + "requires": { + "wrappy": "1" + } + } + } + }, + "ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha512-Z87aSjx3r5c0ZB7bcJqIgIRX5bxR7A4aSzvIbaxd0oTkWBCOoKfuGHiKj60CHVUgg1Phm5yMZzBdt8XqRs73Mw==", + "dev": true, + "requires": { + "readable-stream": "^2.0.1" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==" + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha512-PRT7ZORmwu2MEFt4/fv3Q+mEfN4zetKxufQrkShY2oGvUms9r8otu5HfdyIFHkYXjO7laNsoVGmM2MANfuTA8g==", + "dev": true, + "requires": { + "lcid": "^1.0.0" + } + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==", + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha512-FC5TeK0AwXzq3tUBFtH74naWkPQCEWs4K+xMxWZBlKDWu0bVHXGZa+KKqxKidd7xwhdZ19ZNuF2uO1M/r196HA==", + "dev": true, + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==" + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==" + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==" + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==", + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==" + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "plugin-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "dev": true, + "requires": { + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==" + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha512-s/46sYeylUfHNjI+sA/78FAHlmIuKqI9wNnzEOGehAlUUYeObv5C2mOinXBjyUyWmJ2SfcS2/ydApH4hTF4WXQ==", + "dev": true + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==" + }, + "pretty-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz", + "integrity": "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "purdy": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/purdy/-/purdy-2.2.1.tgz", + "integrity": "sha512-hR6fMofSheE6zc3sybZTcVXZLuRt5vId1aOymjT3JneaMkh/5IwNasN33f/XABJeQ7m4ZhoT+2/Nj9L9z6NWIw==", + "requires": { + "chalk": "0.4.x", + "hoek": "2.x.x", + "joi": "6.x.x" + }, + "dependencies": { + "ansi-styles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "integrity": "sha512-3iF4FIKdxaVYT3JqQuY3Wat/T2t7TRbbQ94Fu50ZUCbLy4TFbTzr90NOHQodQkNqmeEGCw8WbeP78WNi6SKYUA==" + }, + "chalk": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "integrity": "sha512-sQfYDlfv2DGVtjdoQqxS0cEZDroyG8h6TamA6rvxwlrU5BaSLDx9xhatBYl2pxZ7gmpNaPFVwBtdGdu5rQ+tYQ==", + "requires": { + "ansi-styles": "~1.0.0", + "has-color": "~0.1.0", + "strip-ansi": "~0.1.0" + } + }, + "strip-ansi": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", + "integrity": "sha512-behete+3uqxecWlDAm5lmskaSaISA+ThQ4oNNBDTBJt0x2ppR6IPqfZNuj6BLaLJ/Sji4TPZlcRyOis8wXQTLg==" + } + } + }, + "randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "dev": true, + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + } + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "requires": { + "resolve": "^1.1.6" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "^0.1.3" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + } + } + } + }, + "remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", + "dev": true, + "requires": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + } + }, + "remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha512-wigO8/O08XHb8YPzpDDT+QmRANfW6vLqxfaXm1YXhnFf3AkSLyjfG3GEFg4McZkmgL7KvCj5u2KczkvSP6NfHA==", + "dev": true, + "requires": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + }, + "dependencies": { + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", + "dev": true + }, + "repeat-element": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==" + }, + "replace-ext": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", + "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==", + "dev": true + }, + "replace-homedir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", + "integrity": "sha512-CHPV/GAglbIB1tnQgaiysb8H2yCy8WQ7lcEwQ/eT+kLj0QHV8LnJW0zpqpE7RSkrMSRoa+EBoag86clf7WAgSg==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.0" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==", + "dev": true + }, + "requizzle": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", + "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, + "resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha512-NYDgziiroVeDC29xq7bp/CacZERYsA9bXYd1ZmcJlF3BcrZv5pTb4NG7SjdyKDnXZ84aC4vo2u6sNKIA1LCu/A==", + "dev": true, + "requires": { + "value-or-function": "^3.0.0" + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==" + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==", + "requires": { + "ret": "~0.1.10" + } + }, + "sass": { + "version": "1.54.4", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.54.4.tgz", + "integrity": "sha512-3tmF16yvnBwtlPrNBHw/H907j8MlOX8aTBnlNX1yrKx24RKcJGPyLhFUwkoKBKesR3unP93/2z14Ll8NicwQUA==", + "dev": true, + "requires": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "dependencies": { + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "semver-greatest-satisfied-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", + "integrity": "sha512-Ny/iyOzSSa8M5ML46IAx3iXc6tfOsYU2R4AXi2UpHk60Zrgyq6eqPj/xiOfS0rRl/iiQ/rdJkVjw/5cdUyCntQ==", + "dev": true, + "requires": { + "sver-compat": "^1.5.0" + } + }, + "sequencify": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", + "integrity": "sha512-YL8BPm0tp6SlXef/VqYpA/ijmTsDP2ZEXzsnqjkaWS7NP7Bfvw18NboL0O8WCIjy67sOCG3MYSK1PB4GC9XdtQ==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + } + } + } + }, + "shelljs": { + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.6.tgz", + "integrity": "sha512-sK/rjl+frweS4RL1ifxTb7eIXQaliSCDN5meqwwfDIHSWU7zH2KPTa/2hS6EAgGw7wHzJ3rQHfhnLzktfagSZA==", + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, + "shellwords": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==" + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha512-fCvEXfh6NWpm+YSuY2bpXb/VIihqWA6hLsgboC+0nl71Q7N7o2eaCW8mJa/NLvQhs6jpd3VZV4UiUQlV6+lc8g==" + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", + "requires": { + "is-descriptor": "^1.0.0" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==" + }, + "sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==" + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", + "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "requires": { + "extend-shallow": "^3.0.0" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + } + } + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==" + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==", + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + } + } + }, + "stream-consume": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", + "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==" + }, + "stream-exhaust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", + "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", + "dev": true + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-bom-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz", + "integrity": "sha512-yH0+mD8oahBZWnY43vxs4pSinn8SMKAdml/EOGBewoe1Y0Eitd0h2Mg3ZRiXruUW6L4P+lvZiEgbh0NgUGia1w==", + "dev": true, + "requires": { + "first-chunk-stream": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + }, + "sver-compat": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", + "integrity": "sha512-aFTHfmjwizMNlNE6dsGmoAM4lHjL0CyiobWaFiXWSlD7cIxshW422Nb8KbXCmR6z+0ZEPY+daXJrDyh/vuwTyg==", + "dev": true, + "requires": { + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, + "taffydb": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", + "integrity": "sha512-y3JaeRSplks6NYQuCOj3ZFMO3j60rTwbuKCvZxsAraGYH2epusatvZ0baZYA01WsGqJBq/Dl6vOrMUJqyMj8kA==", + "dev": true + }, + "through2": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", + "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "2 || 3" + } + }, + "through2-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", + "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", + "dev": true, + "requires": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + }, + "dependencies": { + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, + "tildify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha512-Y9q1GaV/BO65Z9Yf4NOGMuwt3SGdptkZBnaaKfTQakrDyCLiuO1Kc5wxW4xLdsjzunRtqtOdhekiUFmZbklwYQ==", + "requires": { + "os-homedir": "^1.0.0" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha512-gLCeArryy2yNTRzTGKbZbloctj64jkZ57hj5zdraXue6aFgd6PmvVtEyiUU+hvU0v7q08oVv8r8ev0tRo6bvgw==" + }, + "to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha512-rtwLUQEwT8ZeKQbyFJyomBRYXyE16U5VKuy0ftxLMK/PZb2fkOsg5r9kHdauuVDbsNdIBoC/HCthpidamQFXYA==", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + } + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "requires": { + "is-plain-object": "^2.0.4" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "requires": { + "isobject": "^3.0.1" + } + } + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha512-+QIz37Ly7acM4EMdw2PRN389OneM5+d844tirkGp4dPKzI5OE72V9OsbFp+CIYJDahZ41ZV05hNtcPAQUAm9/Q==", + "dev": true, + "requires": { + "through2": "^2.0.3" + }, + "dependencies": { + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, + "topo": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz", + "integrity": "sha512-vpmONxdZoD0R3hzH0lovwv8QmsqZmGCDE1wXW9YGD/reiDOAbPKEgRDlBCAt8u8nJhav/s/I+r+1gvdpA11x7Q==", + "requires": { + "hoek": "2.x.x" + } + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "dev": true + }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, + "uglify-js": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.0.tgz", + "integrity": "sha512-aTeNPVmgIMPpm1cxXr2Q/nEbvkmV8yq66F3om7X3P/cvOXQ0TMQ64Wk63iyT1gPlmdmGzjGpyLh1f3y8MZWXGg==", + "dev": true + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==" + }, + "underscore": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.4.tgz", + "integrity": "sha512-BQFnUDuAQ4Yf/cYY5LNrK9NCJFKriaRbD9uR1fTeXnBeoa97W0i41qkZfGO9pSo8I5KzjAcSY2XYtdf0oKd7KQ==", + "dev": true + }, + "undertaker": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz", + "integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "fast-levenshtein": "^1.0.0", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + } + }, + "undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha512-UR1khWeAjugW3548EfQmL9Z7pGMlBgXteQpr1IZeZBtnkCJQJIJ1Scj0mb9wQaPvUZ9Q17XqW6TIaPchJkyfqw==", + "dev": true + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "unique-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", + "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", + "dev": true, + "requires": { + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==", + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==", + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==" + } + } + }, + "up": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/up/-/up-1.0.2.tgz", + "integrity": "sha512-PKVGUj7i1qMWSR83H3PZpw1h+21wAr1qxqF/8zgTVHS+sHTsu1zvepQDoDJN0Kv49quNJwWgAKDAK2xPy7jocg==" + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true + }, + "update-browserslist-db": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz", + "integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "dependencies": { + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==" + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha512-aggiKfEEubv3UwRNqTzLInZpAOmKzwdHqEBmW/hBA/mt99eg+b4VrX6i+IRLxU8+WJYfa33rGwRseg4eElUgsQ==" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha512-jdBB2FrWvQC/pnPtIqcLsMaQgjhdb6B7tk1MMyTKapox+tQZbdRP4uLxu/JY0t7fbfDCUMnuelzEYv5GsxHhdg==", + "dev": true + }, + "vinyl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", + "dev": true, + "requires": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + }, + "dependencies": { + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "dev": true + }, + "replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "dev": true + } + } + }, + "vinyl-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-2.0.0.tgz", + "integrity": "sha512-44i5QVLwRPbiRyuiHJ+zJXooNNRXUUifdfYIC1Gm7YTlemMgYQrZ+q1LERS6AYAN8w0xe7n9OgjEYckQjR5+4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.3.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0", + "strip-bom-stream": "^2.0.0", + "vinyl": "^1.1.0" + }, + "dependencies": { + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha512-dhUqc57gSMCo6TX85FLfe51eC/s+Im2MLkAgJwfaRRexR2tA4dd3eLEW4L6efzHc2iNorrRRXITifnDLlRrhaA==", + "dev": true + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha512-AFBWBy9EVRTa/LhEcG8QDP3FvpwZqmvN2QFDuJswFeaVhWnZMp8q3E6Zd90SR04PlIwfGdyVjNyLPyen/ek5CQ==", + "dev": true + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha512-Ci3wnR2uuSAWFMSglZuB8Z2apBdtOyz8CV7dC6/U1XbltXBC+IuutUkXQISz01P+US2ouBuesSbV6zILZ6BuzQ==", + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "vinyl-fs": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "requires": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + }, + "dependencies": { + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, + "vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha512-NiibMgt6VJGJmyw7vtzhctDcfKch4e4n9TBeoWlirb7FMg9/1Ov9k+A5ZRAtywBpRPiyECvQRQllYM8dECegVA==", + "dev": true, + "requires": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha512-+oDh3KYZBoZC8hfocrbrxbLUeaYtQK7J5WU5Br9VqWqmCll3tFJqKp97GC9GmMsVIL0qnx2DgEDVxdo5EZ5sSw==", + "dev": true, + "requires": { + "source-map": "^0.5.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true + } + } + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "optional": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ==", + "dev": true + }, + "winston": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.6.tgz", + "integrity": "sha512-J5Zu4p0tojLde8mIOyDSsmLmcP8I3Z6wtwpTDHx1+hGcdhxcJaAmG4CFtagkb+NiN1M9Ek4b42pzMWqfc9jm8w==", + "requires": { + "async": "^3.2.3", + "colors": "1.0.x", + "cycle": "1.0.x", + "eyes": "0.1.x", + "isstream": "0.1.x", + "stack-trace": "0.0.x" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha512-vAaEaDM946gbNpH5pLVNR+vX2ht6n0Bt3GXwVB1AuAqZosOvHNF3P7wDnh8KLkSqgUh0uh77le7Owgoz+Z9XBw==", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "xmlcreate": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", + "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "y18n": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", + "dev": true + }, + "yargs": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.2.tgz", + "integrity": "sha512-ZEjj/dQYQy0Zx0lgLMLR8QuaqTihnxirir7EwUHp1Axq4e3+k8jXU5K0VLbNvedv1f4EWtBonDIZm0NUr+jCcA==", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.1" + } + }, + "yargs-parser": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.1.tgz", + "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "object.assign": "^4.1.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..610bf67 --- /dev/null +++ b/package.json @@ -0,0 +1,31 @@ +{ + "main": "index.js", + "scripts": { + "update": "npm install", + "start": "node node_modules/gulp/bin/gulp.js" + }, + "author": "Eoxia", + "contributors": [ + { + "name": "Eoxia", + "email": "dev@eoxia.com" + } + ], + "license": "GPLv3", + "devDependencies": { + "gulp": "^4.0.0", + "gulp-autoprefixer": "^6.0.0", + "gulp-concat": "latest", + "gulp-line-ending-corrector": "^1.0.3", + "gulp-rename": "latest", + "gulp-sass": "latest", + "gulp-uglify": "latest", + "gulp-watch": "latest", + "jsdoc": "^3.6.7", + "sass": "latest" + }, + "dependencies": { + "composer": "^4.1.0", + "gulp-phpunit": "^0.26.0" + } +} diff --git a/sql/data.sql b/sql/data.sql new file mode 100644 index 0000000..e560892 --- /dev/null +++ b/sql/data.sql @@ -0,0 +1,2 @@ +INSERT INTO llx_c_actioncomm (id, code, type, libelle, module, active, todo, color, picto, position) VALUES (70, 'AC_TEL_IN', 'system', 'Incoming phone call', NULL, 1, NULL, NULL, NULL, 10); +INSERT INTO llx_c_actioncomm (id, code, type, libelle, module, active, todo, color, picto, position) VALUES (71, 'AC_TEL_OUT', 'system', 'Outgoing phone call', NULL, 1, NULL, NULL, NULL, 11); diff --git a/sql/index.php b/sql/index.php new file mode 100644 index 0000000..17927e6 --- /dev/null +++ b/sql/index.php @@ -0,0 +1,2 @@ + +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU 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 General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + +ALTER TABLE llx_categorie_invoice ADD PRIMARY KEY pk_categorie_invoice (fk_categorie, fk_invoice); +ALTER TABLE llx_categorie_invoice ADD INDEX idx_categorie_invoice_fk_categorie (fk_categorie); +ALTER TABLE llx_categorie_invoice ADD INDEX idx_categorie_invoice_fk_invoice (fk_invoice); +ALTER TABLE llx_categorie_invoice ADD CONSTRAINT fk_categorie_invoice_categorie_rowid FOREIGN KEY (fk_categorie) REFERENCES llx_categorie (rowid); diff --git a/sql/llx_categorie_invoice.sql b/sql/llx_categorie_invoice.sql new file mode 100644 index 0000000..41ba2e4 --- /dev/null +++ b/sql/llx_categorie_invoice.sql @@ -0,0 +1,20 @@ +-- Copyright (C) 2022 EOXIA +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU 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 General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + +CREATE TABLE llx_categorie_invoice( + fk_categorie integer NOT NULL, + fk_invoice integer NOT NULL, + import_key varchar(14) +) ENGINE=innodb; diff --git a/sql/llx_categorie_invoicerec.key.sql b/sql/llx_categorie_invoicerec.key.sql new file mode 100644 index 0000000..a9c55e1 --- /dev/null +++ b/sql/llx_categorie_invoicerec.key.sql @@ -0,0 +1,19 @@ +-- Copyright (C) 2022 EOXIA +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU 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 General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + +ALTER TABLE llx_categorie_invoicerec ADD PRIMARY KEY pk_categorie_invoicerec (fk_categorie, fk_invoicerec); +ALTER TABLE llx_categorie_invoicerec ADD INDEX idx_categorie_invoicerec_fk_categorie (fk_categorie); +ALTER TABLE llx_categorie_invoicerec ADD INDEX idx_categorie_invoicerec_fk_invoicerec (fk_invoicerec); +ALTER TABLE llx_categorie_invoicerec ADD CONSTRAINT fk_categorie_invoicerec_categorie_rowid FOREIGN KEY (fk_categorie) REFERENCES llx_categorie (rowid); diff --git a/sql/llx_categorie_invoicerec.sql b/sql/llx_categorie_invoicerec.sql new file mode 100644 index 0000000..8247d50 --- /dev/null +++ b/sql/llx_categorie_invoicerec.sql @@ -0,0 +1,20 @@ +-- Copyright (C) 2022 EOXIA +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU 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 General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + +CREATE TABLE llx_categorie_invoicerec( + fk_categorie integer NOT NULL, + fk_invoicerec integer NOT NULL, + import_key varchar(14) +) ENGINE=innodb; diff --git a/sql/llx_categorie_timesheet.key.sql b/sql/llx_categorie_timesheet.key.sql new file mode 100644 index 0000000..66432cb --- /dev/null +++ b/sql/llx_categorie_timesheet.key.sql @@ -0,0 +1,19 @@ +-- Copyright (C) 2022 EOXIA +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU 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 General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + +ALTER TABLE llx_categorie_timesheet ADD PRIMARY KEY pk_categorie_timesheet (fk_categorie, fk_timesheet); +ALTER TABLE llx_categorie_timesheet ADD INDEX idx_categorie_timesheet_fk_categorie (fk_categorie); +ALTER TABLE llx_categorie_timesheet ADD INDEX idx_categorie_timesheet_fk_timesheet (fk_timesheet); +ALTER TABLE llx_categorie_timesheet ADD CONSTRAINT fk_categorie_timesheet_categorie_rowid FOREIGN KEY (fk_categorie) REFERENCES llx_categorie (rowid); diff --git a/sql/llx_categorie_timesheet.sql b/sql/llx_categorie_timesheet.sql new file mode 100644 index 0000000..6abdca9 --- /dev/null +++ b/sql/llx_categorie_timesheet.sql @@ -0,0 +1,20 @@ +-- Copyright (C) 2022 EOXIA +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU 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 General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + +CREATE TABLE llx_categorie_timesheet( + fk_categorie integer NOT NULL, + fk_timesheet integer NOT NULL, + import_key varchar(14) +) ENGINE=innodb; diff --git a/sql/llx_doliproject_timesheetdet.sql b/sql/llx_doliproject_timesheetdet.sql new file mode 100644 index 0000000..3b30946 --- /dev/null +++ b/sql/llx_doliproject_timesheetdet.sql @@ -0,0 +1,26 @@ +-- Copyright (C) 2022 EOXIA +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU 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 General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + +CREATE TABLE llx_dolisirh_timesheetdet( + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + date_creation datetime NOT NULL, + qty real, + rang integer DEFAULT 0, + description text, + product_type integer DEFAULT 0, + fk_timesheet integer NOT NULL, + fk_product integer NULL, + fk_parent_line integer NULL +) ENGINE=innodb; diff --git a/sql/llx_dolisirh_timesheet.key.sql b/sql/llx_dolisirh_timesheet.key.sql new file mode 100644 index 0000000..925b9ea --- /dev/null +++ b/sql/llx_dolisirh_timesheet.key.sql @@ -0,0 +1,23 @@ +-- Copyright (C) 2022 EOXIA +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU 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 General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + +ALTER TABLE llx_dolisirh_timesheet ADD INDEX idx_dolisirh_timesheet_rowid (rowid); +ALTER TABLE llx_dolisirh_timesheet ADD INDEX idx_dolisirh_timesheet_ref (ref); +ALTER TABLE llx_dolisirh_timesheet ADD INDEX idx_dolisirh_timesheet_status (status); +ALTER TABLE llx_dolisirh_timesheet ADD INDEX idx_dolisirh_timesheet_fk_user_assign (fk_user_assign); +ALTER TABLE llx_dolisirh_timesheet ADD INDEX idx_dolisirh_timesheet_fk_soc (fk_soc); +ALTER TABLE llx_dolisirh_timesheet ADD INDEX idx_dolisirh_timesheet_fk_project (fk_project); +ALTER TABLE llx_dolisirh_timesheet ADD CONSTRAINT llx_dolisirh_timesheet_fk_user_creat FOREIGN KEY (fk_user_creat) REFERENCES llx_user(rowid); + diff --git a/sql/llx_dolisirh_timesheet.sql b/sql/llx_dolisirh_timesheet.sql new file mode 100644 index 0000000..d09fced --- /dev/null +++ b/sql/llx_dolisirh_timesheet.sql @@ -0,0 +1,40 @@ +-- Copyright (C) 2022 EOXIA +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU 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 General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + + +CREATE TABLE llx_dolisirh_timesheet( + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + ref varchar(128) DEFAULT '(PROV)' NOT NULL, + ref_ext varchar(128), + entity integer DEFAULT 1 NOT NULL, + label varchar(255), + description text, + note_public text, + note_private text, + date_creation datetime NOT NULL, + date_start datetime NOT NULL, + date_end datetime NOT NULL, + tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + last_main_doc varchar(255), + import_key varchar(14), + model_pdf varchar(255), + model_odt varchar(255), + status integer NOT NULL, + fk_user_assign integer NOT NULL, + fk_soc integer, + fk_project integer, + fk_user_creat integer NOT NULL, + fk_user_modif integer +) ENGINE=innodb; diff --git a/sql/llx_dolisirh_timesheet_extrafields.key.sql b/sql/llx_dolisirh_timesheet_extrafields.key.sql new file mode 100644 index 0000000..06c5f06 --- /dev/null +++ b/sql/llx_dolisirh_timesheet_extrafields.key.sql @@ -0,0 +1,16 @@ +-- Copyright (C) 2022 EOXIA +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU 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 General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + +ALTER TABLE llx_dolisirh_timesheet_extrafields ADD INDEX idx_timesheet_fk_object(fk_object); diff --git a/sql/llx_dolisirh_timesheet_extrafields.sql b/sql/llx_dolisirh_timesheet_extrafields.sql new file mode 100644 index 0000000..1c17762 --- /dev/null +++ b/sql/llx_dolisirh_timesheet_extrafields.sql @@ -0,0 +1,22 @@ +-- Copyright (C) 2022 EOXIA +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU 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 General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + +create table llx_dolisirh_timesheet_extrafields( + rowid integer AUTO_INCREMENT PRIMARY KEY, + tms timestamp, + fk_object integer NOT NULL, + import_key varchar(14) -- import key +) ENGINE=innodb; + diff --git a/sql/llx_dolisirh_timesheetdet.key.sql b/sql/llx_dolisirh_timesheetdet.key.sql new file mode 100644 index 0000000..493b4bb --- /dev/null +++ b/sql/llx_dolisirh_timesheetdet.key.sql @@ -0,0 +1,21 @@ +-- Copyright (C) 2022 EOXIA +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU 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 General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + +ALTER TABLE llx_dolisirh_timesheetdet ADD INDEX idx_dolisirh_timesheetdet_rowid (rowid); +ALTER TABLE llx_dolisirh_timesheetdet ADD INDEX idx_dolisirh_timesheetdet_fk_timesheet (fk_timesheet); +ALTER TABLE llx_dolisirh_timesheetdet ADD INDEX idx_dolisirh_timesheetdet_fk_product (fk_product); + +ALTER TABLE llx_dolisirh_timesheetdet ADD CONSTRAINT llx_dolisirh_timesheetdet_fk_timesheet FOREIGN KEY (fk_timesheet) REFERENCES llx_dolisirh_timesheet (rowid); + diff --git a/sql/llx_dolisirh_timesheetdet_extrafields.key.sql b/sql/llx_dolisirh_timesheetdet_extrafields.key.sql new file mode 100644 index 0000000..973021c --- /dev/null +++ b/sql/llx_dolisirh_timesheetdet_extrafields.key.sql @@ -0,0 +1,16 @@ +-- Copyright (C) 2022 EOXIA +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU 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 General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + +ALTER TABLE llx_dolisirh_timesheetdet_extrafields ADD INDEX idx_timesheetdet_fk_object(fk_object); diff --git a/sql/llx_dolisirh_timesheetdet_extrafields.sql b/sql/llx_dolisirh_timesheetdet_extrafields.sql new file mode 100644 index 0000000..be7b878 --- /dev/null +++ b/sql/llx_dolisirh_timesheetdet_extrafields.sql @@ -0,0 +1,22 @@ +-- Copyright (C) 2022 EOXIA +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU 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 General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + +create table llx_dolisirh_timesheetdet_extrafields( + rowid integer AUTO_INCREMENT PRIMARY KEY, + tms timestamp, + fk_object integer NOT NULL, + import_key varchar(14) -- import key +) ENGINE=innodb; + diff --git a/sql/llx_element_workinghours.sql b/sql/llx_element_workinghours.sql new file mode 100644 index 0000000..53a44b9 --- /dev/null +++ b/sql/llx_element_workinghours.sql @@ -0,0 +1,39 @@ +-- Copyright (C) 2021 EOXIA +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU 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 General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + +CREATE TABLE llx_element_workinghours( + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + entity integer DEFAULT 1 NOT NULL, + date_creation datetime NOT NULL, + tms timestamp, + status smallint, + element_type varchar(50), + element_id integer NOT NULL, + schedule_monday varchar(128), + schedule_tuesday varchar(128), + schedule_wednesday varchar(128), + schedule_thursday varchar(128), + schedule_friday varchar(128), + schedule_saturday varchar(128), + schedule_sunday varchar(128), + workinghours_monday integer, + workinghours_tuesday integer, + workinghours_wednesday integer, + workinghours_thursday integer, + workinghours_friday integer, + workinghours_saturday integer, + workinghours_sunday integer, + fk_user_creat integer NOT NULL +) ENGINE=innodb; diff --git a/sql/signature/llx_dolisirh_object_signature.key.sql b/sql/signature/llx_dolisirh_object_signature.key.sql new file mode 100644 index 0000000..34c5c95 --- /dev/null +++ b/sql/signature/llx_dolisirh_object_signature.key.sql @@ -0,0 +1,17 @@ +-- Copyright (C) 2022 EOXIA +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU 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 General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + +ALTER TABLE llx_dolisirh_object_signature ADD INDEX idx_dolisirh_object_signature_rowid (rowid); +ALTER TABLE llx_dolisirh_object_signature ADD CONSTRAINT llx_dolisirh_object_signature_fk_object FOREIGN KEY (fk_object) REFERENCES llx_dolisirh_object(rowid); diff --git a/sql/signature/llx_dolisirh_object_signature.sql b/sql/signature/llx_dolisirh_object_signature.sql new file mode 100644 index 0000000..975dc77 --- /dev/null +++ b/sql/signature/llx_dolisirh_object_signature.sql @@ -0,0 +1,41 @@ +-- Copyright (C) 2022 EOXIA +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU 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 General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see https://www.gnu.org/licenses/. + +CREATE TABLE llx_dolisirh_object_signature( + rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, + entity integer DEFAULT 1 NOT NULL, + date_creation datetime NOT NULL, + tms timestamp, + import_key integer DEFAULT NULL, + status smallint, + role varchar(255), + firstname varchar(255), + lastname varchar(255), + email varchar(255), + phone varchar(255), + society_name varchar(255), + signature_date datetime DEFAULT NULL, + signature_location varchar(255), + signature_comment text DEFAULT NULL, + element_id integer NOT NULL, + element_type varchar(255), + signature text, + stamp text, + last_email_sent_date datetime DEFAULT NULL, + signature_url varchar(255), + transaction_url varchar(255), + object_type varchar(255), + fk_object integer NOT NULL +) ENGINE=innodb; diff --git a/sql/update.sql b/sql/update.sql new file mode 100644 index 0000000..20780bd --- /dev/null +++ b/sql/update.sql @@ -0,0 +1 @@ +UPDATE llx_extrafields SET list = "preg_match('/public/',$_SERVER['PHP_SELF'])?0:1" WHERE name = 'fk_task' AND elementtype = 'ticket' AND type = 'select'; diff --git a/test/index.php b/test/index.php new file mode 100644 index 0000000..17927e6 --- /dev/null +++ b/test/index.php @@ -0,0 +1,2 @@ + + * Copyright (C) 2020 SuperAdmin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file test/phpunit/DolisirhFunctionalTest.php + * \ingroup dolisirh + * \brief Example Selenium test. + * + * Put detailed description here. + */ + +namespace test\functional; + +use PHPUnit_Extensions_Selenium2TestCase_WebDriverException; + +/** + * Class DolisirhFunctionalTest + * + * Requires chromedriver for Google Chrome + * Requires geckodriver for Mozilla Firefox + * + * @fixme Firefox (Geckodriver/Marionette) support + * @todo Opera linux support + * @todo Windows support (IE, Google Chrome, Mozilla Firefox, Safari) + * @todo OSX support (Safari, Google Chrome, Mozilla Firefox) + * + * @package Testdolisirh + */ +class DolisirhFunctionalTest extends \PHPUnit_Extensions_Selenium2TestCase +{ + // TODO: move to a global configuration file? + /** @var string Base URL of the webserver under test */ + protected static $base_url = 'http://dev.zenfusion.fr'; + /** + * @var string Dolibarr admin username + * @see authenticate + */ + protected static $dol_admin_user = 'admin'; + /** + * @var string Dolibarr admin password + * @see authenticate + */ + protected static $dol_admin_pass = 'admin'; + /** @var int Dolibarr module ID */ + private static $module_id = 500000; // TODO: autodetect? + + /** @var array Browsers to test with */ + public static $browsers = array( + array( + 'browser' => 'Google Chrome on Linux', + 'browserName' => 'chrome', + 'sessionStrategy' => 'shared', + 'desiredCapabilities' => array() + ), + // Geckodriver does not keep the session at the moment?! + // XPath selectors also don't seem to work + //array( + // 'browser' => 'Mozilla Firefox on Linux', + // 'browserName' => 'firefox', + // 'sessionStrategy' => 'shared', + // 'desiredCapabilities' => array( + // 'marionette' => true, + // ), + //) + ); + + /** + * Helper function to select links by href + * + * @param string $value Href + * @return mixed Helper string + */ + protected function byHref($value) + { + $anchor = null; + $anchors = $this->elements($this->using('tag name')->value('a')); + foreach ($anchors as $anchor) { + if (strstr($anchor->attribute('href'), $value)) { + break; + } + } + return $anchor; + } + + /** + * Global test setup + * @return void + */ + public static function setUpBeforeClass() + { + } + + /** + * Unit test setup + * @return void + */ + public function setUp() + { + $this->setSeleniumServerRequestsTimeout(3600); + $this->setBrowserUrl(self::$base_url); + } + + /** + * Verify pre conditions + * @return void + */ + protected function assertPreConditions() + { + } + + /** + * Handle Dolibarr authentication + * @return void + */ + private function authenticate() + { + try { + if ($this->byId('login')) { + $login = $this->byId('username'); + $login->clear(); + $login->value('admin'); + $password = $this->byId('password'); + $password->clear(); + $password->value('admin'); + $this->byId('login')->submit(); + } + } catch (PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) { + // Login does not exist. Assume we are already authenticated + } + } + + /** + * Test enabling developer mode + * @return bool + */ + public function testEnableDeveloperMode() + { + $this->url('/admin/const.php'); + $this->authenticate(); + $main_features_level_path = '//input[@value="MAIN_FEATURES_LEVEL"]/following::input[@type="text"]'; + $main_features_level = $this->byXPath($main_features_level_path); + $main_features_level->clear(); + $main_features_level->value('2'); + $this->byName('update')->click(); + // Page reloaded, we need a new XPath + $main_features_level = $this->byXPath($main_features_level_path); + return $this->assertEquals('2', $main_features_level->value(), "MAIN_FEATURES_LEVEL value is 2"); + } + + /** + * Test enabling the module + * + * @depends testEnableDeveloperMode + * @return bool + */ + public function testModuleEnabled() + { + $this->url('/admin/modules.php'); + $this->authenticate(); + $module_status_image_path = '//a[contains(@href, "'.self::$module_id.'")]/img'; + $module_status_image = $this->byXPath($module_status_image_path); + if (strstr($module_status_image->attribute('src'), 'switch_off.png')) { + // Enable the module + $this->byHref('modDolisirh')->click(); + } else { + // Disable the module + $this->byHref('modDolisirh')->click(); + // Reenable the module + $this->byHref('modDolisirh')->click(); + } + // Page reloaded, we need a new Xpath + $module_status_image = $this->byXPath($module_status_image_path); + return $this->assertContains('switch_on.png', $module_status_image->attribute('src'), "Module enabled"); + } + + /** + * Test access to the configuration page + * + * @depends testModuleEnabled + * @return bool + */ + public function testConfigurationPage() + { + $this->url('/custom/dolisirh/admin/setup.php'); + $this->authenticate(); + return $this->assertContains('dolisirh/admin/setup.php', $this->url(), 'Configuration page'); + } + + /** + * Test access to the about page + * + * @depends testConfigurationPage + * @return bool + */ + public function testAboutPage() + { + $this->url('/custom/dolisirh/admin/about.php'); + $this->authenticate(); + return $this->assertContains('dolisirh/admin/about.php', $this->url(), 'About page'); + } + + /** + * Test about page is rendering Markdown + * + * @depends testAboutPage + * @return bool + */ + public function testAboutPageRendersMarkdownReadme() + { + $this->url('/custom/dolisirh/admin/about.php'); + $this->authenticate(); + return $this->assertEquals( + 'Dolibarr Module Template (aka My Module)', + $this->byTag('h1')->text(), + "Readme title" + ); + } + + /** + * Test box is properly declared + * + * @depends testModuleEnabled + * @return bool + */ + public function testBoxDeclared() + { + $this->url('/admin/boxes.php'); + $this->authenticate(); + return $this->assertContains('dolisirhwidget1', $this->source(), "Box enabled"); + } + + /** + * Test trigger is properly enabled + * + * @depends testModuleEnabled + * @return bool + */ + public function testTriggerDeclared() + { + $this->url('/admin/triggers.php'); + $this->authenticate(); + return $this->assertContains( + 'interface_99_modDolisirh_DolisirhTriggers.class.php', + $this->byTag('body')->text(), + "Trigger declared" + ); + } + + /** + * Test trigger is properly declared + * + * @depends testTriggerDeclared + * @return bool + */ + public function testTriggerEnabled() + { + $this->url('/admin/triggers.php'); + $this->authenticate(); + return $this->assertContains( + 'tick.png', + $this->byXPath('//td[text()="interface_99_modDolisirh_MyTrigger.class.php"]/following::img')->attribute('src'), + "Trigger enabled" + ); + } + + /** + * Verify post conditions + * @return void + */ + protected function assertPostConditions() + { + } + + /** + * Unit test teardown + * @return void + */ + public function tearDown() + { + } + + /** + * Global test teardown + * @return void + */ + public static function tearDownAfterClass() + { + } +} diff --git a/test/phpunit/index.php b/test/phpunit/index.php new file mode 100644 index 0000000..17927e6 --- /dev/null +++ b/test/phpunit/index.php @@ -0,0 +1,2 @@ + + * Copyright (C) 2004-2016 Laurent Destailleur + * Copyright (C) 2005-2010 Regis Houssin + * Copyright (C) 2010 François Legastelois + * Copyright (C) 2018 Frédéric France + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/projet/activity/perday.php + * \ingroup projet + * \brief List activities of tasks (per day entry) + */ + +if ( ! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); +if ( ! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); +if ( ! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); +if ( ! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); +if ( ! defined('NOLOGIN')) define("NOLOGIN", 1); // This means this output page does not require to be logged. +if ( ! defined('NOCSRFCHECK')) define("NOCSRFCHECK", 1); // We accept to go on this page from external web site. +if ( ! defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip +if ( ! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); + + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if ( ! $res && ! empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"] . "/main.inc.php"; +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } +if ( ! $res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1)) . "/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1)) . "/main.inc.php"; +if ( ! $res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1))) . "/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1))) . "/main.inc.php"; +// Try main.inc.php using relative path +if ( ! $res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; +if ( ! $res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; +if ( ! $res) die("Include of main fails"); + +dol_print_date(dol_now()); +?> + + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file view/recurringinvoicestatistics.php + * \ingroup dolisirh + * \brief Recurring invoice statistics page + */ + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if ( ! $res && ! empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"] . "/main.inc.php"; +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } +if ( ! $res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1)) . "/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1)) . "/main.inc.php"; +if ( ! $res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1))) . "/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1))) . "/main.inc.php"; +// Try main.inc.php using relative path +if ( ! $res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; +if ( ! $res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; +if ( ! $res) die("Include of main fails"); + +// Libraries +require_once DOL_DOCUMENT_ROOT.'/core/class/dolgraph.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; +require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; +if (!empty($conf->category->enabled)) { + require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; +} + +require_once DOL_DOCUMENT_ROOT.'/custom/dolisirh/class/facturerecstats.class.php'; + +// Global variables definitions +global $db, $langs, $user; + +$WIDTH = DolGraph::getDefaultGraphSizeForStats('width'); +$HEIGHT = DolGraph::getDefaultGraphSizeForStats('height'); + +// Load translation files required by the page +$langs->loadLangs(array('bills', 'companies', 'other')); + +$mode = GETPOST("mode") ? GETPOST("mode") : 'customer'; +if ($mode == 'customer' && !$user->rights->facture->lire) { + accessforbidden(); +} +//if ($mode == 'supplier' && empty($user->rights->fournisseur->facture->lire)) { +// accessforbidden(); +//} + +$object_status = GETPOST('object_status', 'intcomma'); +$typent_id = GETPOST('typent_id', 'int'); +$categ_id = GETPOST('categ_id', 'categ_id'); +$categinvoicerec_id = GETPOST('categinvoicerec_id'); +$userid = GETPOST('userid', 'int'); +$socid = GETPOST('socid', 'int'); +$custcats = GETPOST('custcats', 'array'); +$invoicereccats = GETPOST('invoicereccats', 'array'); + +// Security check +if ($user->socid > 0) { + $action = ''; + $socid = $user->socid; +} + +$nowyear = strftime("%Y", dol_now()); +$year = GETPOST('year') > 0 ? GETPOST('year', 'int') : $nowyear; +$startyear = $year - (empty($conf->global->MAIN_STATS_GRAPHS_SHOW_N_YEARS) ? 2 : max(1, min(10, $conf->global->MAIN_STATS_GRAPHS_SHOW_N_YEARS))); +$endyear = $year; + +/* + * View + */ +if (!empty($conf->category->enabled)) { + $langs->load('categories'); +} +$form = new Form($db); +$formcompany = new FormCompany($db); +$formother = new FormOther($db); + +llxHeader(); + +$picto = 'bill'; +$title = $langs->trans("RecurringInvoicesStatistics"); +$dir = $conf->facture->dir_temp; + +//if ($mode == 'supplier') { +// $picto = 'supplier_invoice'; +// $title = $langs->trans("BillsStatisticsSuppliers"); +// $dir = $conf->fournisseur->facture->dir_temp; +//} + +print load_fiche_titre($title, '', $picto); + +dol_mkdir($dir); + +$stats = new FactureRecStats($db, (int) $socid, $mode, ($userid > 0 ? $userid : 0), ($typent_id > 0 ? $typent_id : 0), ($categ_id > 0 ? $categ_id : 0), ($categinvoicerec_id > 0 ? $categinvoicerec_id : 0)); +if ($mode == 'customer') { + if ($object_status != '' && $object_status >= 0) { + $stats->where .= ' AND f.suspended IN ('.$db->sanitize($object_status).')'; + } + if (is_array($custcats) && !empty($custcats)) { + $stats->from .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_societe as cat ON (fr.fk_soc = cat.fk_soc)'; + $stats->where .= ' AND cat.fk_categorie IN ('.$db->sanitize(implode(',', $custcats)).')'; + } + if (is_array($invoicereccats) && !empty($invoicereccats)) { + $stats->from .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_invoicerec as catinv ON (fr.rowid = catinv.fk_invoicerec)'; + $stats->where .= ' AND catinv.fk_categorie IN ('.$db->sanitize(implode(',', $invoicereccats)).')'; + } +} + +//if ($mode == 'supplier') { +// if ($object_status != '' && $object_status >= 0) { +// $stats->where .= ' AND f.fk_statut IN ('.$db->sanitize($object_status).')'; +// } +// if (is_array($custcats) && !empty($custcats)) { +// $stats->from .= ' LEFT JOIN '.MAIN_DB_PREFIX.'categorie_fournisseur as cat ON (f.fk_soc = cat.fk_soc)'; +// $stats->where .= ' AND cat.fk_categorie IN ('.$db->sanitize(implode(',', $custcats)).')'; +// } +//} + +// Build graphic number of object +$data = $stats->getNbByMonthWithPrevYear($endyear, $startyear, 0, 0, $conf->global->SOCIETE_FISCAL_MONTH_START); + +$filenamenb = $dir."/invoicerecsnbinyear-".$year.".png"; +if ($mode == 'customer') { + $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=dolisirh&file=invoicerecsnbinyear-'.$year.'.png'; +} +//if ($mode == 'supplier') { +// $fileurlnb = DOL_URL_ROOT.'/viewimage.php?modulepart=dolisirh&file=invoicesnbinyear-'.$year.'.png'; +//} + +$px1 = new DolGraph(); +$mesg = $px1->isGraphKo(); +if (!$mesg) { + $px1->SetData($data); + $i = $startyear; + $legend = array(); + while ($i <= $endyear) { + $legend[] = $i; + $i++; + } + $px1->SetLegend($legend); + $px1->SetMaxValue($px1->GetCeilMaxValue()); + $px1->SetWidth($WIDTH); + $px1->SetHeight($HEIGHT); + $px1->SetYLabel($langs->trans("NumberOfRecurringBills")); + $px1->SetShading(3); + $px1->SetHorizTickIncrement(1); + $px1->mode = 'depth'; + $px1->SetTitle($langs->trans("NumberOfRecurringBillsByMonth")); + + $px1->draw($filenamenb, $fileurlnb); +} + +// Build graphic amount of object +$data = $stats->getAmountByMonthWithPrevYear($endyear, $startyear, 0, 0, $conf->global->SOCIETE_FISCAL_MONTH_START); + +$filenameamount = $dir."/invoicerecsamountinyear-".$year.".png"; +if ($mode == 'customer') { + $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=dolisirh&file=invoicerecsamountinyear-'.$year.'.png'; +} +//if ($mode == 'supplier') { +// $fileurlamount = DOL_URL_ROOT.'/viewimage.php?modulepart=billstatssupplier&file=invoicesamountinyear-'.$year.'.png'; +//} + +$px2 = new DolGraph(); +$mesg = $px2->isGraphKo(); +if (!$mesg) { + $px2->SetData($data); + $i = $startyear; + $legend = array(); + while ($i <= $endyear) { + $legend[] = $i; + $i++; + } + $px2->SetLegend($legend); + $px2->SetMaxValue($px2->GetCeilMaxValue()); + $px2->SetMinValue(min(0, $px2->GetFloorMinValue())); + $px2->SetWidth($WIDTH); + $px2->SetHeight($HEIGHT); + $px2->SetYLabel($langs->trans("AmountOfRecurringBills")); + $px2->SetShading(3); + $px2->SetHorizTickIncrement(1); + $px2->mode = 'depth'; + $px2->SetTitle($langs->trans("AmountOfRecurringBillsByMonthHT")); + + $px2->draw($filenameamount, $fileurlamount); +} + +// Build graphic average amount of object +$data = $stats->getAverageByMonthWithPrevYear($endyear, $startyear, 0, $conf->global->SOCIETE_FISCAL_MONTH_START); + +if (empty($user->rights->societe->client->voir) || $user->socid) { + $filename_avg = $dir.'/invoicerecsaverage-'.$user->id.'-'.$year.'.png'; + if ($mode == 'customer') { + $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=dolisirh&file=invoicerecsaverage-'.$user->id.'-'.$year.'.png'; + } +// if ($mode == 'supplier') { +// $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersaverage-'.$user->id.'-'.$year.'.png'; +// } +} else { + $filename_avg = $dir.'/invoicerecsaverage-'.$year.'.png'; + if ($mode == 'customer') { + $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=dolisirh&file=invoicerecsaverage-'.$year.'.png'; + } +// if ($mode == 'supplier') { +// $fileurl_avg = DOL_URL_ROOT.'/viewimage.php?modulepart=orderstatssupplier&file=ordersaverage-'.$year.'.png'; +// } +} + +$px3 = new DolGraph(); +$mesg = $px3->isGraphKo(); +if (!$mesg) { + $px3->SetData($data); + $i = $startyear; + $legend = array(); + while ($i <= $endyear) { + $legend[] = $i; + $i++; + } + $px3->SetLegend($legend); + $px3->SetYLabel($langs->trans("AmountAverage")); + $px3->SetMaxValue($px3->GetCeilMaxValue()); + $px3->SetMinValue($px3->GetFloorMinValue()); + $px3->SetWidth($WIDTH); + $px3->SetHeight($HEIGHT); + $px3->SetShading(3); + $px3->SetHorizTickIncrement(1); + $px3->mode = 'depth'; + $px3->SetTitle($langs->trans("AmountAverage")); + + $px3->draw($filename_avg, $fileurl_avg); +} + +// Show array +$data = $stats->getAllByYear(); +$arrayyears = array(); +foreach ($data as $val) { + $arrayyears[$val['year']] = $val['year']; +} +if (!count($arrayyears)) { + $arrayyears[$nowyear] = $nowyear; +} + +$h = 0; +$head = array(); +$head[$h][0] = DOL_URL_ROOT.'/custom/dolisirh/view/recurringinvoicestatistics.php?mode='.urlencode($mode); +$head[$h][1] = $langs->trans("ByMonthYear"); +$head[$h][2] = 'byyear'; +$h++; + +if ($mode == 'customer') { + $type = 'invoice_stats'; +} +//if ($mode == 'supplier') { +// $type = 'supplier_invoice_stats'; +//} + +complete_head_from_modules($conf, $langs, null, $head, $h, $type); + +print dol_get_fiche_head($head, 'byyear', $langs->trans("Statistics"), -1); + +// We use select_thirdparty_list instead of select_company so we can use $filter and share same code for customer and supplier. +$filter = ''; +if ($mode == 'customer') { + $filter = 's.client in (1,2,3)'; +} +//if ($mode == 'supplier') { +// $filter = 's.fournisseur = 1'; +//} + +print '
'; + +// Show filter box +print '
'; +print ''; +print ''; + +print ''; +print ''; +// Company +print ''; + +// ThirdParty Type +print ''; + +// Category +if (!empty($conf->category->enabled)) { + if ($mode == 'customer') { + $cat_type = Categorie::TYPE_CUSTOMER; + $cat_label = $langs->trans("Category").' '.lcfirst($langs->trans("Customer")); + } +// if ($mode == 'supplier') { +// $cat_type = Categorie::TYPE_SUPPLIER; +// $cat_label = $langs->trans("Category").' '.lcfirst($langs->trans("Supplier")); +// } + print ''; +} + +// Category invoice rec +if (!empty($conf->category->enabled)) { + if ($mode == 'customer') { + $cat_type = 'invoice'; + $cat_label = $langs->trans("Category").' '.lcfirst($langs->trans("RecurringInvoice")); + } +// if ($mode == 'supplier') { +// $cat_type = Categorie::TYPE_SUPPLIER; +// $cat_label = $langs->trans("Category").' '.lcfirst($langs->trans("Supplier")); +// } + print ''; +} + +// User +print ''; +// Status +print ''; +// Year +print ''; +print ''; +print '
'.$langs->trans("Filter").'
'.$langs->trans("ThirdParty").''; +print img_picto('', 'company', 'class="pictofixedwidth"'); +print $form->select_company($socid, 'socid', $filter, 1, 0, 0, array(), 0, 'widthcentpercentminusx maxwidth300'); +print '
'.$langs->trans("ThirdPartyType").''; +$sortparam_typent = (empty($conf->global->SOCIETE_SORT_ON_TYPEENT) ? 'ASC' : $conf->global->SOCIETE_SORT_ON_TYPEENT); // NONE means we keep sort of original array, so we sort on position. ASC, means next function will sort on label. +print $form->selectarray("typent_id", $formcompany->typent_array(0), $typent_id, 1, 0, 0, '', 0, 0, 0, $sortparam_typent, '', 1); +if ($user->admin) { + print ' '.info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1); +} +print '
'.$cat_label.''; + $cate_arbo = $form->select_all_categories($cat_type, null, 'parent', null, null, 1); + print img_picto('', 'category', 'class="pictofixedwidth"'); + print $form->multiselectarray('custcats', $cate_arbo, GETPOST('custcats', 'array'), 0, 0, 'widthcentpercentminusx maxwidth300'); + //print $formother->select_categories($cat_type, $categ_id, 'categ_id', true); + print '
'.$cat_label.''; + $cate_arbo = $form->select_all_categories($cat_type, null, 'parent', null, null, 1); + print img_picto('', 'category', 'class="pictofixedwidth"'); + print $form->multiselectarray('invoicereccats', $cate_arbo, GETPOST('invoicereccats', 'array'), 0, 0, 'widthcentpercentminusx maxwidth300'); + //print $formother->select_categories($cat_type, $categ_id, 'categ_id', true); + print '
'.$langs->trans("CreatedBy").''; +print img_picto('', 'user', 'class="pictofixedwidth"'); +print $form->select_dolusers($userid, 'userid', 1, '', 0, '', '', 0, 0, 0, '', 0, '', 'widthcentpercentminusx maxwidth300'); +print '
'.$langs->trans("Status").''; +if ($mode == 'customer') { + $liststatus = array('0'=>$langs->trans("Draft"), '1'=>$langs->trans("Disable")); + print $form->selectarray('object_status', $liststatus, $object_status, 1); +} +//if ($mode == 'supplier') { +// $liststatus = array('0'=>$langs->trans("BillStatusDraft"), '1'=>$langs->trans("BillStatusNotPaid"), '2'=>$langs->trans("BillStatusPaid")); +// print $form->selectarray('object_status', $liststatus, $object_status, 1); +//} +print '
'.$langs->trans("Year").''; +if (!in_array($year, $arrayyears)) { + $arrayyears[$year] = $year; +} +if (!in_array($nowyear, $arrayyears)) { + $arrayyears[$nowyear] = $nowyear; +} +arsort($arrayyears); +print $form->selectarray('year', $arrayyears, $year, 0, 0, 0, '', 0, 0, 0, '', 'width75'); +print '
'; +print '
'; +print '

'; + +print '
'; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +$oldyear = 0; +foreach ($data as $val) { + $year = $val['year']; + while ($year && $oldyear > $year + 1) { // If we have empty year + $oldyear--; + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + } + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + $oldyear = $year; +} + +print '
'.$langs->trans("Year").''.$langs->trans("NumberOfRecurringBills").'%'.$langs->trans("AmountTotal").'%'.$langs->trans("AmountAverage").'%
0 ? '&userid='.$userid : '').'">'.$oldyear.'000
0 ? '&userid='.$userid : '').'">'.$year.''.$val['nb'].''.(!empty($val['nb_diff']) && $val['nb_diff'] < 0 ? '' : '+').round(!empty($val['nb_diff']) ? $val['nb_diff'] : 0).'%'.price(price2num($val['total'], 'MT'), 1).''.( !empty($val['total_diff']) && $val['total_diff'] < 0 ? '' : '+').round(!empty($val['total_diff']) ? $val['total_diff'] : 0).'%'.price(price2num($val['avg'], 'MT'), 1).''.(!empty($val['avg_diff']) && $val['avg_diff'] < 0 ? '' : '+').round(!empty($val['avg_diff']) ? $val['avg_diff'] : 0).'%
'; +print '
'; + +print '
'; + +// Show graphs +print '
'; +if ($mesg) { + print $mesg; +} else { + print $px1->show(); + print "
\n"; + print $px2->show(); + print "
\n"; + print $px3->show(); +} +print '
'; + +print '
'; +print '
'; + +print dol_get_fiche_end(); + +// End of page +llxFooter(); +$db->close(); diff --git a/view/timesheet/index.php b/view/timesheet/index.php new file mode 100644 index 0000000..17927e6 --- /dev/null +++ b/view/timesheet/index.php @@ -0,0 +1,2 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file timesheet_agenda.php + * \ingroup dolisirh + * \brief Tab of events on TimeSheet + */ + +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Do not create database handler $db +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Do not load object $user +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); // Do not load object $mysoc +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1'); // Do not load object $langs +//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION', '1'); // Do not check injection attack on GET parameters +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION', '1'); // Do not check injection attack on POST parameters +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK', '1'); // Do not check CSRF attack (test on referer + on token if option MAIN_SECURITY_CSRF_WITH_TOKEN is on). +//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on) +//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK', '1'); // Do not check style html tag into posted data +//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu +//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php +//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library +//if (! defined("NOLOGIN")) define("NOLOGIN", '1'); // If this page is public (can be called outside logged session). This include the NOIPCHECK too. +//if (! defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip +//if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT', 'auto'); // Force lang to a particular value +//if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule'); // Force authentication handler +//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN', 1); // The main.inc.php does not make a redirect if not logged, instead show simple error message +//if (! defined("FORCECSP")) define('FORCECSP', 'none'); // Disable all Content Security Policies +//if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET +//if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) { + $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +} +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { + $i--; $j--; +} +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +} +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) { + $res = @include "../main.inc.php"; +} +if (!$res && file_exists("../../main.inc.php")) { + $res = @include "../../main.inc.php"; +} +if (!$res && file_exists("../../../main.inc.php")) { + $res = @include "../../../main.inc.php"; +} +if (!$res && file_exists("../../../../main.inc.php")) { + $res = @include "../../../../main.inc.php"; +} +if (!$res) { + die("Include of main fails"); +} + +require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; +require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; +dol_include_once('/dolisirh/class/timesheet.class.php'); +dol_include_once('/dolisirh/lib/dolisirh_timesheet.lib.php'); + + +// Load translation files required by the page +$langs->loadLangs(array("dolisirh@dolisirh", "other")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$cancel = GETPOST('cancel', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +if (GETPOST('actioncode', 'array')) { + $actioncode = GETPOST('actioncode', 'array', 3); + if (!count($actioncode)) { + $actioncode = '0'; + } +} else { + $actioncode = GETPOST("actioncode", "alpha", 3) ? GETPOST("actioncode", "alpha", 3) : (GETPOST("actioncode") == '0' ? '0' : (empty($conf->global->AGENDA_DEFAULT_FILTER_TYPE_FOR_OBJECT) ? '' : $conf->global->AGENDA_DEFAULT_FILTER_TYPE_FOR_OBJECT)); +} +$search_agenda_label = GETPOST('search_agenda_label'); + +$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); +$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); +if (empty($page) || $page == -1) { + $page = 0; +} // If $page is not defined, or '' or -1 +$offset = $limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; +if (!$sortfield) { + $sortfield = 'a.datep,a.id'; +} +if (!$sortorder) { + $sortorder = 'DESC,DESC'; +} + +// Initialize technical objects +$object = new TimeSheet($db); +$extrafields = new ExtraFields($db); +$project = new Project($db); +$diroutputmassaction = $conf->dolisirh->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('timesheetagenda', 'globalcard')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals +if ($id > 0 || !empty($ref)) { + $upload_dir = $conf->dolisirh->multidir_output[!empty($object->entity) ? $object->entity : $conf->entity]."/".$object->id; +} + +// There is several ways to check permission. +// Set $enablepermissioncheck to 1 to enable a minimum low level of checks +$enablepermissioncheck = 0; +if ($enablepermissioncheck) { + $permissiontoread = $user->rights->dolisirh->timesheet->read; + $permissiontoadd = $user->rights->dolisirh->timesheet->write; +} else { + $permissiontoread = 1; + $permissiontoadd = 1; +} + +// Security check (enable the most restrictive one) +//if ($user->socid > 0) accessforbidden(); +//if ($user->socid > 0) $socid = $user->socid; +//$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); +//restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); +if (empty($conf->dolisirh->enabled)) accessforbidden(); +if (!$permissiontoread) accessforbidden(); + + +/* + * Actions + */ + +$parameters = array('id'=>$id); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} + +if (empty($reshook)) { + // Cancel + if (GETPOST('cancel', 'alpha') && !empty($backtopage)) { + header("Location: ".$backtopage); + exit; + } + + // Purge search criteria + if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers + $actioncode = ''; + $search_agenda_label = ''; + } +} + + + +/* + * View + */ + +$form = new Form($db); + +if ($object->id > 0) { + $title = $langs->trans("Agenda"); + //if (! empty($conf->global->MAIN_HTML_TITLE) && preg_match('/thirdpartynameonly/',$conf->global->MAIN_HTML_TITLE) && $object->name) $title=$object->name." - ".$title; + $help_url = 'EN:Module_Agenda_En'; + $morejs = array("/dolisirh/js/dolisirh.js.php"); + $morecss = array("/dolisirh/css/dolisirh.css"); + + llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss); + + if (!empty($conf->notification->enabled)) { + $langs->load("mails"); + } + $head = timesheetPrepareHead($object); + + + print dol_get_fiche_head($head, 'agenda', $langs->trans("TimeSheet"), -1, 'dolisirh@dolisirh'); + + // Object card + // ------------------------------------------------------------ + $linkback = ''.$langs->trans("BackToList").''; + + $morehtmlref = '
'; + // Thirdparty + if (! empty($conf->societe->enabled)) { + $object->fetch_thirdparty(); + $morehtmlref .= $langs->trans('ThirdParty') . ' : ' . (is_object($object->thirdparty) ? $object->thirdparty->getNomUrl(1) : ''); + } + // Project + if (! empty($conf->projet->enabled)) { + $langs->load("projects"); + $morehtmlref .= '
' . $langs->trans('Project') . ' '; + if (! empty($object->fk_project)) { + $project->fetch($object->fk_project); + $morehtmlref .= ': ' . $project->getNomUrl(1, '', 1); + } else { + $morehtmlref .= ''; + } + } + $morehtmlref .= '
'; + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + print '
'; + print '
'; + + $object->info($object->id); + dol_print_object_info($object, 1); + + print '
'; + + print dol_get_fiche_end(); + + + + // Actions buttons + + $objthirdparty = $object; + $objcon = new stdClass(); + + $out = '&origin='.urlencode($object->element.'@'.$object->module).'&originid='.urlencode($object->id); + $urlbacktopage = $_SERVER['PHP_SELF'].'?id='.$object->id; + $out .= '&backtopage='.urlencode($urlbacktopage); + $permok = $user->rights->agenda->myactions->create; + if ((!empty($objthirdparty->id) || !empty($objcon->id)) && $permok) { + //$out.='trans("AddAnAction"),'filenew'); + //$out.=""; + } + + + print '
'; + + if (!empty($conf->agenda->enabled)) { + if (!empty($user->rights->agenda->myactions->create) || !empty($user->rights->agenda->allactions->create)) { + print ''.$langs->trans("AddAction").''; + } else { + print ''.$langs->trans("AddAction").''; + } + } + + print '
'; + + if (!empty($conf->agenda->enabled) && (!empty($user->rights->agenda->myactions->read) || !empty($user->rights->agenda->allactions->read))) { + $param = '&id='.$object->id.'&socid='.$socid; + if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { + $param .= '&contextpage='.urlencode($contextpage); + } + if ($limit > 0 && $limit != $conf->liste_limit) { + $param .= '&limit='.urlencode($limit); + } + + + //print load_fiche_titre($langs->trans("ActionsOnTimeSheet"), '', ''); + + // List of all actions + $filters = array(); + $filters['search_agenda_label'] = $search_agenda_label; + + // TODO Replace this with same code than into list.php + show_actions_done($conf, $langs, $db, $object, null, 0, $actioncode, '', $filters, $sortfield, $sortorder, $object->module); + } +} + +// End of page +llxFooter(); +$db->close(); diff --git a/view/timesheet/timesheet_attendants.php b/view/timesheet/timesheet_attendants.php new file mode 100644 index 0000000..8c2b2f3 --- /dev/null +++ b/view/timesheet/timesheet_attendants.php @@ -0,0 +1,481 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file view/timesheet/timesheet_attendants.php + * \ingroup dolisirh + * \brief Page to add/edit/view timesheet_signature + */ + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) { + $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +} +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { + $i--; $j--; +} +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +} +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) { + $res = @include "../main.inc.php"; +} +if (!$res && file_exists("../../main.inc.php")) { + $res = @include "../../main.inc.php"; +} +if (!$res && file_exists("../../../main.inc.php")) { + $res = @include "../../../main.inc.php"; +} +if (!$res && file_exists("../../../../main.inc.php")) { + $res = @include "../../../../main.inc.php"; +} +if (!$res) { + die("Include of main fails"); +} + +require_once DOL_DOCUMENT_ROOT . '/core/lib/images.lib.php'; +require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php'; +require_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; + +require_once __DIR__ . '/../../class/timesheet.class.php'; +require_once __DIR__ . '/../../lib/dolisirh_timesheet.lib.php'; +require_once __DIR__ . '/../../lib/dolisirh_function.lib.php'; + +global $db, $hookmanager, $langs, $user; + +// Load translation files required by the page +$langs->loadLangs(array("dolisirh@dolisirh", "other")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'timesheetsignature'; // To manage different context of search +$backtopage = GETPOST('backtopage', 'alpha'); +$cancel = GETPOST('cancel', 'aZ09'); + +// Initialize technical objects +$object = new TimeSheet($db); +$signatory = new TimeSheetSignature($db); +$usertmp = new User($db); +$contact = new Contact($db); +$form = new Form($db); +$project = new Project($db); +$thirdparty = new Societe($db); + +$object->fetch($id); + +$hookmanager->initHooks(array($object->element.'signature', 'globalcard')); // Note that conf->hooks_modules contains array + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals + +//Security check +$object_type = $object->element; +$permissiontoread = $user->rights->dolisirh->$object_type->read; +$permissiontoadd = $user->rights->dolisirh->$object_type->write; +$permissiontodelete = $user->rights->dolisirh->$object_type->delete; + +if ( ! $permissiontoread) accessforbidden(); + +/* + * Actions + */ + +$parameters = array(); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + +if (empty($backtopage) || ($cancel && empty($id))) { + if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) { + $backtopage = dol_buildpath('/dolisirh/view/'. $object->element .'/' . $object->element .'_attendants.php', 1) . '?id=' . ($object->id > 0 ? $object->id : '__ID__'); + } +} + +// Action to add internal attendant +if ($action == 'addSocietyAttendant') { + $error = 0; + $object->fetch($id); + $attendant_id = GETPOST('user_attendant'); + + if ( ! $error) { + $role = strtoupper(GETPOST('attendantRole')); + $result = $signatory->setSignatory($object->id, $object->element, 'user', array($attendant_id), strtoupper($object->element).'_' . $role, $role == 'SOCIETY_RESPONSIBLE ' ? 0 : 1); + if ($result > 0) { + $usertmp = $user; + $usertmp->fetch($attendant_id); + setEventMessages($langs->trans('AddAttendantMessage') . ' ' . $usertmp->firstname . ' ' . $usertmp->lastname, array()); + $signatory->call_trigger('DOLISIRHSIGNATURE_ADDATTENDANT', $user); + // Creation attendant OK + $urltogo = str_replace('__ID__', $result, $backtopage); + $urltogo = preg_replace('/--IDFORBACKTOPAGE--/', $id, $urltogo); // New method to autoselect project after a New on another form object creation + header("Location: " . $urltogo); + exit; + } else { + // Creation attendant KO + if ( ! empty($object->errors)) setEventMessages(null, $object->errors, 'errors'); + else setEventMessages($object->error, null, 'errors'); + } + } +} + +// Action to add record +if ($action == 'addSignature') { + $signatoryID = GETPOST('signatoryID'); + $data = json_decode(file_get_contents('php://input'), true); + + $signatory->fetch($signatoryID); + $signatory->signature = $data['signature']; + $signatory->signature_date = dol_now('tzuser'); + + if ( ! $error) { + $result = $signatory->update($user, false); + + if ($result > 0) { + // Creation signature OK + $signatory->setSigned($user, 0); + setEventMessages($langs->trans('SignatureEvent') . ' ' . $signatory->firstname . ' ' . $signatory->lastname, array()); + $urltogo = str_replace('__ID__', $result, $backtopage); + $urltogo = preg_replace('/--IDFORBACKTOPAGE--/', $id, $urltogo); // New method to autoselect project after a New on another form object creation + header("Location: " . $urltogo); + exit; + } else { + // Creation signature KO + if ( ! empty($signatory->errors)) setEventMessages(null, $signatory->errors, 'errors'); + else setEventMessages($signatory->error, null, 'errors'); + } + } +} + +// Action to set status STATUS_ABSENT +if ($action == 'setAbsent') { + $signatoryID = GETPOST('signatoryID'); + + $signatory->fetch($signatoryID); + + if ( ! $error) { + $result = $signatory->setAbsent($user, 0); + if ($result > 0) { + // set absent OK + setEventMessages($langs->trans('Attendant') . ' ' . $signatory->firstname . ' ' . $signatory->lastname . ' ' . $langs->trans('SetAbsentAttendant'), array()); + $urltogo = str_replace('__ID__', $result, $backtopage); + $urltogo = preg_replace('/--IDFORBACKTOPAGE--/', $id, $urltogo); // New method to autoselect project after a New on another form object creation + header("Location: " . $urltogo); + exit; + } else { + // set absent KO + if ( ! empty($signatory->errors)) setEventMessages(null, $signatory->errors, 'errors'); + else setEventMessages($signatory->error, null, 'errors'); + } + } +} + +// Action to send Email +if ($action == 'send') { + $signatoryID = GETPOST('signatoryID'); + $signatory->fetch($signatoryID); + + if ( ! $error) { + $langs->load('mails'); + + if (!dol_strlen($signatory->email)) { + if ($signatory->element_type == 'user') { + $usertmp = $user; + $usertmp->fetch($signatory->element_id); + if (dol_strlen($usertmp->email)) { + $signatory->email = $usertmp->email; + $signatory->update($user, true); + } + } else if ($signatory->element_type == 'socpeople') { + $contact->fetch($signatory->element_id); + if (dol_strlen($contact->email)) { + $signatory->email = $contact->email; + $signatory->update($user, true); + } + } + } + + $sendto = $signatory->email; + + if (dol_strlen($sendto) && ( ! empty($conf->global->MAIN_MAIL_EMAIL_FROM))) { + require_once DOL_DOCUMENT_ROOT . '/core/class/CMailFile.class.php'; + + $from = $conf->global->MAIN_MAIL_EMAIL_FROM; + $url = dol_buildpath('/custom/dolisirh/public/signature/add_signature.php?track_id=' . $signatory->signature_url . '&type=' . $object->element, 3); + + $message = $langs->trans('SignatureEmailMessage') . ' ' . $url; + $subject = $langs->trans('SignatureEmailSubject') . ' ' . $object->ref; + + // Create form object + // Send mail (substitutionarray must be done just before this) + $mailfile = new CMailFile($subject, $sendto, $from, $message, array(), array(), array(), "", "", 0, -1, '', '', '', '', 'mail'); + + if ($mailfile->error) { + setEventMessages($mailfile->error, $mailfile->errors, 'errors'); + } else { + if ( ! empty($conf->global->MAIN_MAIL_SMTPS_ID)) { + $result = $mailfile->sendfile(); + if ($result) { + $signatory->last_email_sent_date = dol_now('tzuser'); + $signatory->update($user, true); + $signatory->setPending($user, false); + setEventMessages($langs->trans('SendEmailAt') . ' ' . $signatory->email, array()); + // This avoid sending mail twice if going out and then back to page + header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id); + exit; + } else { + $langs->load("other"); + $mesg = '
'; + if ($mailfile->error) { + $mesg .= $langs->transnoentities('ErrorFailedToSendMail', dol_escape_htmltag($from), dol_escape_htmltag($sendto)); + $mesg .= '
' . $mailfile->error; + } else { + $mesg .= $langs->transnoentities('ErrorFailedToSendMail', dol_escape_htmltag($from), dol_escape_htmltag($sendto)); + } + $mesg .= '
'; + setEventMessages($mesg, null, 'warnings'); + } + } else { + setEventMessages($langs->trans('ErrorSetupEmail'), '', 'errors'); + } + } + } else { + $langs->load("errors"); + setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("MailTo")), null, 'warnings'); + dol_syslog('Try to send email with no recipient defined', LOG_WARNING); + } + } else { + // Mail sent KO + if ( ! empty($signatory->errors)) setEventMessages(null, $signatory->errors, 'errors'); + else setEventMessages($signatory->error, null, 'errors'); + } +} + +// Action to delete attendant +if ($action == 'deleteAttendant') { + $signatoryToDeleteID = GETPOST('signatoryID'); + $signatory->fetch($signatoryToDeleteID); + + if ( ! $error) { + $result = $signatory->setDeleted($user, 0); + if ($result > 0) { + setEventMessages($langs->trans('DeleteAttendantMessage') . ' ' . $signatory->firstname . ' ' . $signatory->lastname, array()); + // Deletion attendant OK + $urltogo = str_replace('__ID__', $result, $backtopage); + $urltogo = preg_replace('/--IDFORBACKTOPAGE--/', $id, $urltogo); // New method to autoselect project after a New on another form object creation + header("Location: " . $urltogo); + exit; + } else { + // Deletion attendant KO + if ( ! empty($object->errors)) setEventMessages(null, $object->errors, 'errors'); + else setEventMessages($object->error, null, 'errors'); + } + } +} + +/* + * View + */ + +$title = $langs->trans("TimeSheetAttendants"); +$help_url = ''; +$morejs = array("/dolisirh/js/signature-pad.min.js", "/dolisirh/js/dolisirh.js.php"); +$morecss = array("/dolisirh/css/dolisirh.css"); + +llxHeader('', $title, $help_url, '', '', '', $morejs, $morecss); + +// Part to show record +if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) { + if ( ! empty($object->id)) $res = $object->fetch_optionals(); + + // Object card + // ------------------------------------------------------------ + + $prepareHead = $object->element . 'PrepareHead'; + $head = $prepareHead($object); + print dol_get_fiche_head($head, 'attendants', $langs->trans("TimeSheet"), -1, 'dolisirh@dolisirh'); + + $linkback = ''.$langs->trans("BackToList").''; + + $morehtmlref = '
'; + // Thirdparty + if (! empty($conf->societe->enabled)) { + $object->fetch_thirdparty(); + $morehtmlref .= $langs->trans('ThirdParty') . ' : ' . (is_object($object->thirdparty) ? $object->thirdparty->getNomUrl(1) : ''); + } + // Project + if (! empty($conf->projet->enabled)) { + $langs->load("projects"); + $morehtmlref .= '
' . $langs->trans('Project') . ' '; + if (! empty($object->fk_project)) { + $project->fetch($object->fk_project); + $morehtmlref .= ': ' . $project->getNomUrl(1, '', 1); + } else { + $morehtmlref .= ''; + } + } + $morehtmlref .= '
'; + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + print '
'; + + print dol_get_fiche_end(); + + print '
'; ?> + + status == $object::STATUS_DRAFT ) : ?> +
+
+
trans('DisclaimerSignatureTitle') ?>
+
trans("TimeSheetMustBeValidatedToSign") ?>
+
+ trans("GoToValidate") ?>; +
+ + + '; + + if ($signatory->checkSignatoriesSignatures($object->id, $object->element) && $object->status < $object::STATUS_LOCKED) { + print '' . $langs->trans("GoToLock") . ''; + } + + //Society attendants -- Participants de la société + $society_intervenants = $signatory->fetchSignatory(strtoupper($object->element).'_SOCIETY_ATTENDANT', $object->id, $object->element); + $society_responsible = $signatory->fetchSignatory(strtoupper($object->element).'_SOCIETY_RESPONSIBLE', $object->id, $object->element); + + $society_intervenants = array_merge($society_intervenants, $society_responsible); + + print load_fiche_titre($langs->trans("Attendants"), '', ''); + + print ''; + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + $already_added_users = array(); + $j = 1; + if (is_array($society_intervenants) && ! empty($society_intervenants) && $society_intervenants > 0) { + foreach ($society_intervenants as $element) { + $usertmp = $user; + $usertmp->fetch($element->element_id); + print ''; + print ''; + print ''; + print ''; + $already_added_users[$element->element_id] = $element->element_id; + $j++; + } + } else { + print ''; + } + + if ($object->status == $object::STATUS_DRAFT && $conf->global->DOLISIRH_TIMESHEET_ADD_ATTENDANTS && $permissiontoadd) { + print ''; + print ''; + print ''; + print ''; + print ''; + + //Participants interne + print ''; + print ''; + print ''; + print '
' . $langs->trans("Name") . '' . $langs->trans("Role") . '' . $langs->trans("SignatureLink") . '' . $langs->trans("SendMailDate") . '' . $langs->trans("SignatureDate") . '' . $langs->trans("Status") . '' . $langs->trans("ActionsSignature") . '' . $langs->trans("Signature") . '
'; + print $usertmp->getNomUrl(1); + print ''; + print $langs->trans($element->role); + print ''; + if ($object->status == $object::STATUS_VALIDATED) { + $signatureUrl = dol_buildpath('/custom/dolisirh/public/signature/add_signature.php?track_id=' . $element->signature_url . '&type=' . $object->element, 3); + print ''; + } else { + print '-'; + } + + print ''; + print dol_print_date($element->last_email_sent_date, 'dayhour'); + print ''; + print dol_print_date($element->signature_date, 'dayhour'); + print ''; + print $element->getLibStatut(5); + print ''; + if ($permissiontoadd && $object->status < $object::STATUS_LOCKED) { + require __DIR__ . "/../../core/tpl/signature/dolisirh_signature_action_view.tpl.php"; + } + print ''; + if ($element->signature != $langs->transnoentities("FileGenerated") && $permissiontoadd) { + require __DIR__ . "/../../core/tpl/signature/dolisirh_signature_view.tpl.php"; + } + print '
'; + print $langs->trans('NoSocietyAttendants'); + print '
'; + print $form->select_dolusers('', 'user_attendant', 1, $already_added_users, 0, '', '', $conf->entity); + print ''; + print ''; + print ajax_combobox('attendantRole'); + print ''; + print '-'; + print ''; + print '-'; + print ''; + print '-'; + print ''; + print '-'; + print ''; + print ''; + print ''; + print '-'; + print '
'; + print ''; + } + print '
'; +} + +// End of page +llxFooter(); +$db->close(); + diff --git a/view/timesheet/timesheet_card.php b/view/timesheet/timesheet_card.php new file mode 100644 index 0000000..dbe01d0 --- /dev/null +++ b/view/timesheet/timesheet_card.php @@ -0,0 +1,940 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file view/timesheet/timesheet_card.php + * \ingroup dolisirh + * \brief Page to create/edit/view timesheet + */ + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) { + $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +} +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { + $i--; $j--; +} +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +} +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) { + $res = @include "../main.inc.php"; +} +if (!$res && file_exists("../../main.inc.php")) { + $res = @include "../../main.inc.php"; +} +if (!$res && file_exists("../../../main.inc.php")) { + $res = @include "../../../main.inc.php"; +} +if (!$res && file_exists("../../../../main.inc.php")) { + $res = @include "../../../../main.inc.php"; +} +if (!$res) { + die("Include of main fails"); +} + +// Libraries +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; +require_once DOL_DOCUMENT_ROOT.'/holiday/class/holiday.class.php'; + +require_once __DIR__ . '/../../class/timesheet.class.php'; +require_once __DIR__ . '/../../class/workinghours.class.php'; +require_once __DIR__ . '/../../lib/dolisirh_timesheet.lib.php'; +require_once __DIR__ . '/../../lib/dolisirh_function.lib.php'; + +// Global variables definitions +global $conf, $db, $hookmanager, $langs, $mysoc, $user; + +// Load translation files required by the page +$langs->loadLangs(array("dolisirh@dolisirh", "other")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$confirm = GETPOST('confirm', 'alpha'); +$cancel = GETPOST('cancel', 'aZ09'); +$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'timesheetcard'; // To manage different context of search +$backtopage = GETPOST('backtopage', 'alpha'); +$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha'); +$lineid = GETPOST('lineid', 'int'); +$year = (GETPOST("year", 'int') ? GETPOST("year", "int") : date("Y")); +$month = (GETPOST("month", 'int') ? GETPOST("month", "int") : date("m")); +$day = (GETPOST("day", 'int') ? GETPOST("day", "int") : date("d")); + +// Initialize technical objects +$object = new TimeSheet($db); +$objectline = new TimeSheetLine($db); +$signatory = new TimeSheetSignature($db); +$extrafields = new ExtraFields($db); +$project = new Project($db); +$product = new Product($db); +$workinghours = new Workinghours($db); +$holiday = new Holiday($db); +$task = new Task($db); +$usertmp = new User($db); + +$hookmanager->initHooks(array('timesheetcard', 'globalcard')); // Note that conf->hooks_modules contains array + +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); + +// Initialize array of search criterias +$search_all = GETPOST("search_all", 'alpha'); +$search = array(); +foreach ($object->fields as $key => $val) { + if (GETPOST('search_'.$key, 'alpha')) { + $search[$key] = GETPOST('search_'.$key, 'alpha'); + } +} + +if (empty($action) && empty($id) && empty($ref)) { + $action = 'view'; +} + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once. + +$permissiontoread = $user->rights->dolisirh->timesheet->read; +$permissiontoadd = $user->rights->dolisirh->timesheet->write; // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php +$permissiontodelete = $user->rights->dolisirh->timesheet->delete || ($permissiontoadd && isset($object->status) && $object->status == $object::STATUS_DRAFT); +$permissionnote = $user->rights->dolisirh->timesheet->write; // Used by the include of actions_setnotes.inc.php + +$upload_dir = $conf->dolisirh->multidir_output[isset($object->entity) ? $object->entity : 1]; + +// Security check (enable the most restrictive one) +if (empty($conf->dolisirh->enabled)) accessforbidden(); +if (!$permissiontoread) accessforbidden(); + +/* + * Actions + */ + +$parameters = array(); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} + +if (empty($reshook)) { + $error = 0; + + $backurlforlist = dol_buildpath('/dolisirh/view/timesheet/timesheet_list.php', 1); + + if (empty($backtopage) || ($cancel && empty($id))) { + if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) { + if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) { + $backtopage = $backurlforlist; + } else { + $backtopage = dol_buildpath('/dolisirh/view/timesheet/timesheet_card.php', 1).'?id='.((!empty($id) && $id > 0) ? $id : '__ID__'); + } + } + } + + $triggermodname = 'TIMESHEET_MODIFY'; // Name of trigger action code to execute when we modify record + + if (($action == 'add' || $action == 'update') && $permissiontoadd && !$cancel) { + $usertmp->fetch(GETPOST('fk_user_assign')); + $date_start = dol_mktime(0, 0, 0, GETPOST('date_startmonth', 'int'), GETPOST('date_startday', 'int'), GETPOST('date_startyear', 'int')); + $date_end = dol_mktime(0, 0, 0, GETPOST('date_endmonth', 'int'), GETPOST('date_endday', 'int'), GETPOST('date_endyear', 'int')); + $filter = ' AND ptt.task_date BETWEEN ' . "'" .dol_print_date($date_start, 'dayrfc') . "'" . ' AND ' . "'" . dol_print_date($date_end, 'dayrfc'). "'"; + $alltimespent = $task->fetchAllTimeSpent($usertmp, $filter); + foreach ($alltimespent as $timespent) { + $task->fetchObjectLinked(null, '', $timespent->timespent_id, 'project_task_time'); + if (isset($task->linkedObjects['dolisirh_timesheet'])) { + $error++; + } + } + + if ($date_start > $date_end) { + setEventMessages($langs->trans('ErrorDateTimeSheet', dol_print_date($date_start, 'dayreduceformat'), dol_print_date($date_end, 'dayreduceformat')), null, 'errors'); + if ($action == 'add') { + $action = 'create'; + } elseif ($action == 'update') { + $action = 'edit'; + } + } + + if ($conf->global->DOLISIRH_TIMESHEET_CHECK_DATE_END > 0) { + if ($date_end > dol_now()) { + setEventMessages($langs->trans('ErrorDateEndTimeSheet', dol_print_date($date_end, 'dayreduceformat'), dol_print_date(dol_now(), 'dayreduceformat')), null, 'errors'); + if ($action == 'add') { + $action = 'create'; + } elseif ($action == 'update') { + $action = 'edit'; + } + } + } + + if ($error > 0) { + setEventMessages($langs->trans('ErrorLinkedElementTimeSheetTimeSpent', $usertmp->getFullName($langs), dol_print_date($date_start, 'dayreduceformat'), dol_print_date($date_end, 'dayreduceformat')), null, 'errors'); + if ($action == 'add') { + $action = 'create'; + } elseif ($action == 'update') { + $action = 'edit'; + } + } + } + + // Actions cancel, add, update, update_extras, confirm_validate, confirm_delete, confirm_deleteline, confirm_clone, confirm_close, confirm_setdraft, confirm_reopen + $conf->global->MAIN_DISABLE_PDF_AUTOUPDATE = 1; + include DOL_DOCUMENT_ROOT.'/core/actions_addupdatedelete.inc.php'; + + // Action to build doc + include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php'; + + if ($action == 'set_thirdparty' && $permissiontoadd) { + $object->setValueFrom('fk_soc', GETPOST('fk_soc', 'int'), '', '', 'date', '', $user, $triggermodname); + } + + if ($action == 'classin' && $permissiontoadd) { + $object->setProject(GETPOST('projectid', 'int')); + } + + // Action to add line + if ($action == 'addline' && $permissiontoadd) { + // Get parameters + $qty = GETPOST('qty'); + $prod_entry_mode = GETPOST('prod_entry_mode'); + + $now = dol_now(); + + if ($prod_entry_mode == 'free') { + $product_type = GETPOST('type'); + $description = GETPOST('dp_desc', 'restricthtml'); + + // Check parameters + if ($product_type < 0) { + setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Type')), null, 'errors'); + $error++; + } + if (empty($description)) { + setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Description')), null, 'errors'); + $error++; + } + + $objectline->description = $description; + $objectline->product_type = $product_type; + } elseif ($prod_entry_mode == 'predef') { + $product_id = GETPOST('idprod'); + if ($product_id > 0) { + $product->fetch($product_id); + $objectline->fk_product = $product_id; + $objectline->product_type = 0; + } else { + $error++; + } + } else { + $error++; + } + + // Initialize object timesheet line + $objectline->date_creation = $object->db->idate($now); + $objectline->qty = $qty; + $objectline->rang = 0; + $objectline->fk_timesheet = $id; + $objectline->fk_parent_line = 0; + + if ( ! $error) { + $result = $objectline->insert($user, false); + if ($result > 0) { + // Creation timesheet line OK + $urltogo = str_replace('__ID__', $result, $backtopage); + $urltogo = preg_replace('/--IDFORBACKTOPAGE--/', $id, $urltogo); // New method to autoselect project after a New on another form object creation + header("Location: " . $urltogo); + exit; + } else { + // Creation timesheet line KO + if ( ! empty($objectline->errors)) setEventMessages(null, $objectline->errors, 'errors'); + else setEventMessages($objectline->error, null, 'errors'); + } + } + } + + // Action to edit line + if ($action == 'updateline' && $permissiontoadd) { + // Get parameters + $qty = GETPOST('qty'); + $description = GETPOST('product_desc', 'restricthtml'); + + $objectline->fetch($lineid); + + // Initialize object timesheet line + $objectline->qty = $qty; + $objectline->description = $description; + + if ( ! $error) { + $result = $objectline->update($user, false); + if ($result > 0) { + // Update timesheet line OK + $urltogo = str_replace('__ID__', $result, $backtopage); + $urltogo = preg_replace('/--IDFORBACKTOPAGE--/', $parent_id, $urltogo); // New method to autoselect project after a New on another form object creation + header("Location: " . $urltogo); + exit; + } else { + // Update timesheet line KO + if ( ! empty($objectline->errors)) setEventMessages(null, $objectline->errors, 'errors'); + else setEventMessages($objectline->error, null, 'errors'); + } + } + } + + // Action to set status STATUS_LOCKED + if ($action == 'confirm_setLocked' && $permissiontoadd) { + $errorlinked = 0; + $object->fetch($id); + if ( ! $error) { + $usertmp->fetch($object->fk_user_assign); + $filter = ' AND ptt.task_date BETWEEN ' . "'" .dol_print_date($object->date_start, 'dayrfc') . "'" . ' AND ' . "'" . dol_print_date($object->date_end, 'dayrfc'). "'"; + $alltimespent = $task->fetchAllTimeSpent($usertmp, $filter); + foreach ($alltimespent as $timespent) { + $task->fetchObjectLinked(null, '', $timespent->timespent_id, 'project_task_time'); + if (!isset($task->linkedObjects['dolisirh_timesheet'])) { + $task->id = $timespent->timespent_id; + $task->element = 'project_task_time'; + $task->add_object_linked('dolisirh_timesheet', $object->id); + } else { + $errorlinked++; + } + } + if ($errorlinked == 0) { + $object->setLocked($user, false); + // Set locked OK + $urltogo = str_replace('__ID__', $result, $backtopage); + $urltogo = preg_replace('/--IDFORBACKTOPAGE--/', $id, $urltogo); // New method to autoselect project after a New on another form object creation + header("Location: " . $urltogo); + exit; + } + } else { + // Set locked KO + if ( ! empty($object->errors)) setEventMessages(null, $object->errors, 'errors'); + else setEventMessages($object->error, null, 'errors'); + } + + if ($errorlinked > 0) { + setEventMessages($langs->trans('ErrorLinkedElementTimeSheetTimeSpent', $usertmp->getFullName($langs), dol_print_date($object->date_start, 'dayreduceformat'), dol_print_date($object->date_end, 'dayreduceformat')), null, 'errors'); + } + } + + // Action to set status STATUS_ARCHIVED + if ($action == 'setArchived' && $permissiontoadd) { + $object->fetch($id); + if ( ! $error) { + $result = $object->setArchived($user, false); + if ($result > 0) { + // Set Archived OK + $urltogo = str_replace('__ID__', $result, $backtopage); + $urltogo = preg_replace('/--IDFORBACKTOPAGE--/', $id, $urltogo); // New method to autoselect project after a New on another form object creation + header("Location: " . $urltogo); + exit; + } else { + // Set Archived KO + if ( ! empty($object->errors)) setEventMessages(null, $object->errors, 'errors'); + else setEventMessages($object->error, null, 'errors'); + } + } + } + + // Actions to send emails + $triggersendname = 'DOLISIRH_TIMESHEET_SENTBYMAIL'; + $autocopy = 'MAIN_MAIL_AUTOCOPY_TIMESHEET_TO'; + $trackid = 'timesheet'.$object->id; + include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php'; +} + +/* + * View + */ + +$form = new Form($db); +$formfile = new FormFile($db); +$formproject = new FormProjets($db); + +$title = $langs->trans("TimeSheet"); +$help_url = ''; +$morejs = array("/dolisirh/js/dolisirh.js.php"); +$morecss = array("/dolisirh/css/dolisirh.css"); + +llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss); + +// Part to create +if ($action == 'create') { + if (empty($permissiontoadd)) { + accessforbidden($langs->trans('NotEnoughPermissions'), 0, 1); + exit; + } + + print load_fiche_titre($langs->trans("NewTimeSheet"), '', 'dolisirh32px@dolisirh'); + + print '
'; + print ''; + print ''; + if ($backtopage) { + print ''; + } + if ($backtopageforcancel) { + print ''; + } + + print dol_get_fiche_head(array(), ''); + + // Set some default values + //if (! GETPOSTISSET('fieldname')) $_POST['fieldname'] = 'myvalue'; + + print ''."\n"; + + $object->fields['label']['default'] = $langs->trans('TimeSheet') . ' ' . dol_print_date(dol_mktime(0, 0, 0, $month, $day, $year), "%B %Y") . ' ' . $user->getFullName($langs, 0, 0); + $object->fields['fk_project']['default'] = $conf->global->DOLISIRH_HR_PROJECT; + $object->fields['fk_user_assign']['default'] = $user->id; + + $date_start = dol_mktime(0, 0, 0, GETPOST('date_startmonth', 'int'), GETPOST('date_startday', 'int'), GETPOST('date_startyear', 'int')); + $date_end = dol_mktime(0, 0, 0, GETPOST('date_endmonth', 'int'), GETPOST('date_endday', 'int'), GETPOST('date_endyear', 'int')); + + $_POST['date_start'] = $date_start; + $_POST['date_end'] = $date_end; + + if ($conf->global->DOLISIRH_TIMESHEET_PREFILL_DATE && empty($_POST['date_start']) && empty($_POST['date_end'])) { + $firstday = dol_get_first_day($year, $month); + $firstday = dol_getdate($firstday); + + $_POST['date_startday'] = $firstday['mday']; + $_POST['date_startmonth'] = $firstday['mon']; + $_POST['date_startyear'] = $firstday['year']; + + $lastday = dol_get_last_day($year, $month); + $lastday = dol_getdate($lastday); + + $_POST['date_endday'] = $lastday['mday']; + $_POST['date_endmonth'] = $lastday['mon']; + $_POST['date_endyear'] = $lastday['year']; + } + $object->fields['note_public']['visible'] = 1; + $object->fields['note_private']['visible'] = 1; + + // Common attributes + include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_add.tpl.php'; + + // Categories + if (!empty($conf->categorie->enabled)) { + print '"; + } + + // Other attributes + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_add.tpl.php'; + + print '
'.$langs->trans("Categories").''; + $cate_arbo = $form->select_all_categories('timesheet', '', 'parent', 64, 0, 1); + print img_picto('', 'category').$form->multiselectarray('categories', $cate_arbo, GETPOST('categories', 'array'), '', 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0); + print "
'."\n"; + + print dol_get_fiche_end(); + + print $form->buttonsSaveCancel("Create"); + + print '
'; + + //dol_set_focus('input[name="ref"]'); +} + +// Part to edit record +if (($id || $ref) && $action == 'edit') { + print load_fiche_titre($langs->trans("ModifyTimeSheet"), '', 'dolisirh@dolisirh'); + + print '
'; + print ''; + print ''; + print ''; + if ($backtopage) { + print ''; + } + if ($backtopageforcancel) { + print ''; + } + + print dol_get_fiche_head(); + + print ''."\n"; + + $date_start = dol_mktime(0, 0, 0, GETPOST('date_startmonth', 'int'), GETPOST('date_startday', 'int'), GETPOST('date_startyear', 'int')); + $date_end = dol_mktime(0, 0, 0, GETPOST('date_endmonth', 'int'), GETPOST('date_endday', 'int'), GETPOST('date_endyear', 'int')); + + $_POST['date_start'] = (!empty($date_start) ? $date_start : $object->date_start); + $_POST['date_end'] = (!empty($date_end) ? $date_end : $object->date_end); + + $object->fields['note_public']['visible'] = 1; + $object->fields['note_private']['visible'] = 1; + + // Common attributes + include DOL_DOCUMENT_ROOT.'/core/tpl/commonfields_edit.tpl.php'; + + // Tags-Categories + if ($conf->categorie->enabled) { + print '"; + } + + // Other attributes + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_edit.tpl.php'; + + print '
'.$langs->trans("Categories").''; + $cate_arbo = $form->select_all_categories('timesheet', '', 'parent', 64, 0, 1); + $c = new Categorie($db); + $cats = $c->containing($object->id, 'timesheet'); + $arrayselected = array(); + if (is_array($cats)) { + foreach ($cats as $cat) { + $arrayselected[] = $cat->id; + } + } + print img_picto('', 'category').$form->multiselectarray('categories', $cate_arbo, $arrayselected, '', 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0); + print "
'; + + print dol_get_fiche_end(); + + print $form->buttonsSaveCancel(); + + print '
'; +} + +// Part to show record +if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) { + $res = $object->fetch_optionals(); + + $head = timesheetPrepareHead($object); + print dol_get_fiche_head($head, 'card', $langs->trans("TimeSheet"), -1, 'dolisirh@dolisirh'); + + $formconfirm = ''; + // setDraft confirmation + if (($action == 'setDraft' && (empty($conf->use_javascript_ajax) || !empty($conf->dol_use_jmobile))) // Output when action = clone if jmobile or no js + || (!empty($conf->use_javascript_ajax) && empty($conf->dol_use_jmobile))) { // Always output when not jmobile nor js + $formconfirm .= $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('ReOpenTimeSheet'), $langs->trans('ConfirmReOpenTimeSheet', $object->ref), 'confirm_setdraft', '', 'yes', 'actionButtonInProgress', 350, 600); + } + // setPendingSignature confirmation + if (($action == 'setPendingSignature' && (empty($conf->use_javascript_ajax) || !empty($conf->dol_use_jmobile))) // Output when action = clone if jmobile or no js + || (!empty($conf->use_javascript_ajax) && empty($conf->dol_use_jmobile))) { // Always output when not jmobile nor js + $formconfirm .= $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('ValidateTimeSheet'), $langs->trans('ConfirmValidateTimeSheet', $object->ref), 'confirm_validate', '', 'yes', 'actionButtonPendingSignature', 350, 600); + } + // setLocked confirmation + if (($action == 'setLocked' && (empty($conf->use_javascript_ajax) || !empty($conf->dol_use_jmobile))) // Output when action = clone if jmobile or no js + || (!empty($conf->use_javascript_ajax) && empty($conf->dol_use_jmobile))) { // Always output when not jmobile nor js + $formconfirm .= $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('LockTimeSheet'), $langs->trans('ConfirmLockTimeSheet', $object->ref), 'confirm_setLocked', '', 'yes', 'actionButtonLock', 350, 600); + } + // Confirmation to delete + if ($action == 'delete') { + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('DeleteTimeSheet'), $langs->trans('ConfirmDeleteObject'), 'confirm_delete', '', 0, 1); + } + // Confirmation to delete line + if ($action == 'ask_deleteline') { + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id . '&lineid=' . $lineid, $langs->trans('DeleteProductLine'), $langs->trans('ConfirmDeleteProductLine'), 'confirm_deleteline', '', 0, 1); + } + // Confirmation remove file + if ($action == 'removefile') { + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id . '&file=' . GETPOST('file') . '&entity=' . $conf->entity, $langs->trans('RemoveFileTimeSheet'), $langs->trans('ConfirmRemoveFileTimeSheet'), 'remove_file', '', 'yes', 1, 350, 600); + } + + // Call Hook formConfirm + $parameters = array('formConfirm' => $formconfirm, 'lineid' => $lineid); + $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if (empty($reshook)) { + $formconfirm .= $hookmanager->resPrint; + } elseif ($reshook > 0) { + $formconfirm = $hookmanager->resPrint; + } + + // Print form confirm + print $formconfirm; + + // Object card + // ------------------------------------------------------------ + $linkback = '' . $langs->trans("BackToList") . ''; + + $morehtmlref = '
'; + // Thirdparty + if (!empty($conf->societe->enabled)) { + $object->fetch_thirdparty(); + $morehtmlref .= $langs->trans('ThirdParty') . ' : ' . (is_object($object->thirdparty) ? $object->thirdparty->getNomUrl(1) : ''); + } + // Project + if (!empty($conf->projet->enabled)) { + $langs->load("projects"); + $morehtmlref .= '
' . $langs->trans('Project') . ' '; + if (!empty($object->fk_project)) { + $project->fetch($object->fk_project); + $morehtmlref .= ': ' . $project->getNomUrl(1, '', 1); + } else { + $morehtmlref .= ''; + } + } + $morehtmlref .= '
'; + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + print '
'; + print '
'; + print '
'; + print '' . "\n"; + + // Common attributes + //$keyforbreak='fieldkeytoswitchonsecondcolumn'; // We change column just before this field + + unset($object->fields['fk_project']); // Hide field already shown in banner + unset($object->fields['fk_soc']); // Hide field already shown in banner + + include DOL_DOCUMENT_ROOT . '/core/tpl/commonfields_view.tpl.php'; + + // Categories + if ($conf->categorie->enabled) { + print '"; + } + + $now = dol_now(); + $datestart = dol_getdate($object->date_start, false, 'Europe/Paris'); + //$firstdaytoshow = dol_get_first_day($datestart['year'], $datestart['mon']); + //$firstdaytoshowgmt = dol_get_first_day($datestart['year'], $datestart['mon'], true); + + // Due to Dolibarr issue in common field add we do substract 12 hours in timestamp + $firstdaytoshow = $object->date_start - 12 * 60 * 60; + $firstdaytoshowgmt = $object->date_start - 12 * 60 * 60; + //$dayInMonth = cal_days_in_month(CAL_GREGORIAN, $datestart['mon'], $datestart['year']); + $dayInMonth = num_between_day($object->date_start, $object->date_end, 1); + //$lastdaytoshow = dol_get_last_day($datestart['year'], $datestart['mon']); + $lastdaytoshow = $object->date_end - 12 * 60 * 60; + $currentDayCurrent = date('d', $now); + $currentMonth = date('m', $now); + $isavailable = array(); + $workinghoursArray = $workinghours->fetchCurrentWorkingHours($object->fk_user_assign, 'user'); + $workinghoursMonth = 0; + $nbworkinghoursMonth = 0; + if ($currentMonth == $datestart['mon']) { + $dayInMonthCurrent = $dayInMonth; + } else { + $dayInMonthCurrent = $dayInMonth; + } + + for ($idw = 0; $idw < $dayInMonth; $idw++) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); // $firstdaytoshow is a date with hours = 0 + $dayinloopfromfirstdaytoshowgmt = dol_time_plus_duree($firstdaytoshowgmt, $idw, 'd'); // $firstdaytoshow is a date with hours = 0 + + $statusofholidaytocheck = Holiday::STATUS_APPROVED; + + $isavailablefordayanduser = $holiday->verifDateHolidayForTimestamp($object->fk_user_assign, $dayinloopfromfirstdaytoshow, $statusofholidaytocheck); + $isavailable[$dayinloopfromfirstdaytoshow] = $isavailablefordayanduser; // in projectLinesPerWeek later, we are using $firstdaytoshow and dol_time_plus_duree to loop on each day + + $test = num_public_holiday($dayinloopfromfirstdaytoshowgmt, $dayinloopfromfirstdaytoshowgmt + 86400, $mysoc->country_code); + if ($test) { + $isavailable[$dayinloopfromfirstdaytoshow] = array('morning' => false, 'afternoon' => false, 'morning_reason' => 'public_holiday', 'afternoon_reason' => 'public_holiday'); + } + } + + $tasksarray = $task->getTasksArray(0, 0, 0, 0, 0, '', '', '', $object->fk_user_assign, 0, array()); + + if (count($tasksarray) > 0) { + $usertmp->fetch($object->fk_user_assign); + $j = 0; + $level = 0; + $projectsrole = $task->getUserRolesForProjectsOrTasks($usertmp, 0, 0, 0, 1); + $tasksrole = $task->getUserRolesForProjectsOrTasks(0, $usertmp, 0, 0, 1); + $restrictviewformytask = ((!isset($conf->global->PROJECT_TIME_SHOW_TASK_NOT_ASSIGNED)) ? 2 : $conf->global->PROJECT_TIME_SHOW_TASK_NOT_ASSIGNED); + $conf->global->DOLISIRH_SHOW_ONLY_FAVORITE_TASKS = 0; + $totalforvisibletasks = projectLinesPerDayOnMonth($j, $firstdaytoshow, $lastdaytoshow, $usertmp, 0, $tasksarray, $level, $projectsrole, $tasksrole, 0, $restrictviewformytask, $isavailable, 0, array(), array(), $dayInMonth, 1); + } + + print ''; + print ''; + print ''; + print ''; + + // Other attributes. Fields from hook formObjectOptions and Extrafields. + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php'; + + print '
' . $langs->trans("Categories") . ''; + print $form->showCategories($object->id, 'timesheet', 1); + print "
'; + print $langs->trans("Total"); + for ($idw = 0; $idw < $dayInMonth; $idw++) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + if ($isavailable[$dayinloopfromfirstdaytoshow]['morning'] && $isavailable[$dayinloopfromfirstdaytoshow]['afternoon']) { + $currentDay = date('l', $dayinloopfromfirstdaytoshow); + $currentDay = 'workinghours_' . strtolower($currentDay); + $workinghoursMonth += $workinghoursArray->{$currentDay} * 60; + if ($workinghoursArray->{$currentDay} / 60 > 0) { + $nbworkinghoursMonth++; + } + if ($totalforvisibletasks[$dayinloopfromfirstdaytoshow] > 0) { + $nbconsumedworkinghoursMonth++; + } + } + } + print ' - ' . $langs->trans("ExpectedWorkedHoursMonthTimeSheet", dol_print_date($firstdaytoshow, "dayreduceformat"), (($dayInMonth == $dayInMonthCurrent) ? dol_print_date($lastdaytoshow, "dayreduceformat") : dol_print_date($now, "dayreduceformat"))) . ' : ' . (($workinghoursMonth != 0) ? convertSecondToTime($workinghoursMonth, 'allhourmin') : '00:00') . ''; + print '' . ' - ' . $langs->trans("ExpectedWorkedDayMonth") . ' ' . $nbworkinghoursMonth . ''; + print ''; + print '
'; + print $langs->trans("Total"); + $workinghoursMonth = 0; + for ($idw = 0; $idw < $dayInMonthCurrent; $idw++) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + if ($isavailable[$dayinloopfromfirstdaytoshow]['morning'] && $isavailable[$dayinloopfromfirstdaytoshow]['afternoon']) { + $currentDay = date('l', $dayinloopfromfirstdaytoshow); + $currentDay = 'workinghours_' . strtolower($currentDay); + $workinghoursMonth += $workinghoursArray->{$currentDay} * 60; + } + } + $totalspenttime = $workinghoursMonth/60/60; + print ' - ' . $langs->trans("SpentWorkedHoursMonth", dol_print_date($firstdaytoshow, "dayreduceformat"), (($dayInMonth == $dayInMonthCurrent) ? dol_print_date($lastdaytoshow, "dayreduceformat") : dol_print_date($now, "dayreduceformat"))) . ' : ' . (($workinghoursMonth != 0) ? convertSecondToTime($workinghoursMonth, 'allhourmin') : '00:00') . ''; + print '
'; + print $langs->trans("Total"); + if (!empty($totalforvisibletasks)) { + foreach ($totalforvisibletasks as $tasksingle) { + $totalconsumedtime += $tasksingle; + } + } + $diffworkinghoursMonth = $nbworkinghoursMonth - $nbconsumedworkinghoursMonth; + if ($diffworkinghoursMonth < 0) { + $morecss = colorStringToArray($conf->global->DOLISIRH_EXCEEDED_TIME_SPENT_COLOR); + } else if ($diffworkinghoursMonth > 0) { + $morecss = colorStringToArray($conf->global->DOLISIRH_NOT_EXCEEDED_TIME_SPENT_COLOR); + } else if ($diffworkinghoursMonth == 0) { + $morecss = colorStringToArray($conf->global->DOLISIRH_PERFECT_TIME_SPENT_COLOR); + } + print ' - '.$langs->trans("ConsumedWorkedHoursMonth", dol_print_date($firstdaytoshow, "dayreduceformat"), (($dayInMonth == $dayInMonthCurrent) ? dol_print_date($lastdaytoshow, "dayreduceformat") : dol_print_date($now, "dayreduceformat"))).' : '.convertSecondToTime($totalconsumedtime, 'allhourmin').''; + print '' . ' - ' . $langs->trans("ConsumedWorkedDayMonth") . ' ' . (!empty($nbconsumedworkinghoursMonth) ? $nbconsumedworkinghoursMonth : 0) . ''; + print ''; + print '
'; + print $langs->trans("Total"); + $difftotaltime = $totalspenttime * 60 * 60 - $totalconsumedtime; + if ($difftotaltime < 0) { + $morecss = colorStringToArray($conf->global->DOLISIRH_EXCEEDED_TIME_SPENT_COLOR); + $morecssnotice = 'error'; + $noticetitle = $langs->trans('TimeSpentDiff', dol_print_date($firstdaytoshow, "dayreduceformat"), (($dayInMonth == $dayInMonthCurrent) ? dol_print_date($lastdaytoshow, "dayreduceformat") : dol_print_date($now, "dayreduceformat")), dol_print_date(dol_mktime(0, 0, 0, $datestart['mon'], $datestart['mday'], $datestart['year']), "%B %Y")); + } else if ($difftotaltime > 0) { + $morecss = colorStringToArray($conf->global->DOLISIRH_NOT_EXCEEDED_TIME_SPENT_COLOR); + $morecssnotice = 'warning'; + $noticetitle = $langs->trans('TimeSpentMustBeCompleted', dol_print_date($firstdaytoshow, "dayreduceformat"), (($dayInMonth == $dayInMonthCurrent) ? dol_print_date($lastdaytoshow, "dayreduceformat") : dol_print_date($now, "dayreduceformat")), dol_print_date(dol_mktime(0, 0, 0, $datestart['mon'], $datestart['mday'], $datestart['year']), "%B %Y")); + } else if ($difftotaltime == 0) { + $morecss = colorStringToArray($conf->global->DOLISIRH_PERFECT_TIME_SPENT_COLOR); + $morecssnotice = 'success'; + $noticetitle = $langs->trans('TimeSpentPerfect'); + } + print ' - '.$langs->trans("DiffSpentAndConsumedWorkedHoursMonth", dol_print_date($firstdaytoshow, "dayreduceformat"), (($dayInMonth == $dayInMonthCurrent) ? dol_print_date($lastdaytoshow, "dayreduceformat") : dol_print_date($now, "dayreduceformat"))).' : '.(($difftotaltime != 0) ? convertSecondToTime(abs($difftotaltime), 'allhourmin') : '00:00').''; + print '
'; + print '
'; + print '
'; + + $usertmp->fetch($object->fk_user_assign); + + print '
'; ?> + + +
+
+
trans('ErrorConfigWorkingHours') ?>
+
+ trans("GoToWorkingHours", $usertmp->getFullName($langs)) ?> +
+ + + + + table_element_line)) { + // Show object lines + $result = $object->getLinesArray(); + + print '
+ + + + + + '; + + if (!empty($conf->use_javascript_ajax) && $object->status == 0) { + include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php'; + } + + print '
'; + if (!empty($object->lines) || ($object->status == $object::STATUS_DRAFT && $permissiontoadd && $action != 'selectlines' && $action != 'editline')) { + print ''; + } + + if (!empty($object->lines)) { + if ($permissiontoadd) { + $user->rights->timesheet = new stdClass(); + $user->rights->timesheet->creer = 1; + $object->statut = $object::STATUS_DRAFT; + if ($object->status >= $object::STATUS_VALIDATED) { + $disableedit = 1; + $disableremove = 1; + $disablemove = 1; + } + } + $object->printObjectLines($action, $mysoc, null, GETPOST('lineid', 'int'), 1); ?> + + status == 0 && $permissiontoadd && $action != 'selectlines') { + if ($action != 'editline') { + // Add products/services form + $object->socid = 0; + $parameters = array(); + $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + if (empty($reshook)) $object->formAddObjectLine(1, $mysoc, $soc); ?> + + lines) || ($object->status == $object::STATUS_DRAFT && $permissiontoadd && $action != 'selectlines' && $action != 'editline')) { + print '
'; + } + print '
'; + + print "
\n"; + } + + // Buttons for actions + if ($action != 'presend' && $action != 'editline') { + print '
'."\n"; + $parameters = array(); + $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } + + if (empty($reshook) && $permissiontoadd) { + // Modify + print '' . $langs->trans("Modify") . ''; + + // Validate + print '' . $langs->trans("Validate") . ''; + + // ReOpen + print '' . $langs->trans("ReOpenDoli") . ''; + + // Sign + print '' . $langs->trans("Sign") . ''; + + // Lock + print '' . $langs->trans("Lock") . ''; + + // Send + //@TODO changer le send to + //print '' . $langs->trans('SendMail') . ''; + + // Archive + print '' . $langs->trans("Archive") . ''; + + // Delete (need delete permission, or if draft, just need create/modify permission) + //print dolGetButtonAction($langs->trans('Delete'), '', 'delete', $_SERVER['PHP_SELF'].'?id='.$object->id.'&action=delete&token='.newToken(), '', $permissiontodelete || ($object->status == $object::STATUS_DRAFT && $permissiontoadd)); + } + print '
'."\n"; + } + + // Select mail models is same action as presend + if (GETPOST('modelselected')) { + $action = 'presend'; + } + + if ($action != 'presend') { + print '
'; + print ''; // ancre + + $includedocgeneration = 1; + + // Documents + if ($includedocgeneration) { + $objref = dol_sanitizeFileName($object->ref); + $dir_files = $object->element . 'document/' . $objref; + $filedir = $upload_dir . '/' . $dir_files; + $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id; + $genallowed = $permissiontoadd; // If you can read, you can build the PDF to read content + $delallowed = $permissiontodelete; // If you can create/edit, you can remove a file on card + + print dolisirhshowdocuments('dolisirh:TimeSheetDocument', $dir_files, $filedir, $urlsource, $genallowed, $object->status == $object::STATUS_LOCKED ? $delallowed : 0, $conf->global->DOLISIRH_TIMESHEETDOCUMENT_DEFAULT_MODEL, 1, 0, 0, 0, 0, '', '', '', $langs->defaultlang, $object, 0, 'removefile', $object->status == $object::STATUS_LOCKED && empty(dol_dir_list($filedir)), $langs->trans('TimeSheetMustBeLocked')); + } + + print '
'; + + $MAXEVENT = 10; + + $morehtmlcenter = dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-list-alt imgforviewmode', dol_buildpath('/dolisirh/view/timesheet/timesheet_agenda.php', 1).'?id='.$object->id); + + // List of actions on element + include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php'; + $formactions = new FormActions($db); + $somethingshown = $formactions->showactions($object, $object->element.'@'.$object->module, (is_object($object->thirdparty) ? $object->thirdparty->id : 0), 1, '', $MAXEVENT, '', $morehtmlcenter); + + print '
'; + } + + //Select mail models is same action as presend + if (GETPOST('modelselected')) { + $action = 'presend'; + } + + // Presend form + $modelmail = 'timesheet'; + $defaulttopic = 'InformationMessage'; + $diroutput = $conf->dolisirh->dir_output; + $trackid = 'timesheet'.$object->id; + + include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php'; +} + +// End of page +llxFooter(); +$db->close(); diff --git a/view/timesheet/timesheet_list.php b/view/timesheet/timesheet_list.php new file mode 100644 index 0000000..78ba92f --- /dev/null +++ b/view/timesheet/timesheet_list.php @@ -0,0 +1,782 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file timesheet_list.php + * \ingroup dolisirh + * \brief List page for timesheet + */ + +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Do not create database handler $db +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Do not load object $user +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); // Do not load object $mysoc +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1'); // Do not load object $langs +//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION', '1'); // Do not check injection attack on GET parameters +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION', '1'); // Do not check injection attack on POST parameters +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK', '1'); // Do not check CSRF attack (test on referer + on token if option MAIN_SECURITY_CSRF_WITH_TOKEN is on). +//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on) +//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK', '1'); // Do not check style html tag into posted data +//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu +//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php +//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library +//if (! defined("NOLOGIN")) define("NOLOGIN", '1'); // If this page is public (can be called outside logged session). This include the NOIPCHECK too. +//if (! defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip +//if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT', 'auto'); // Force lang to a particular value +//if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule'); // Force authentication handler +//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN', 1); // The main.inc.php does not make a redirect if not logged, instead show simple error message +//if (! defined("FORCECSP")) define('FORCECSP', 'none'); // Disable all Content Security Policies +//if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET +//if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification +//if (! defined('NOSESSION')) define('NOSESSION', '1'); // On CLI mode, no need to use web sessions + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) { + $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +} +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { + $i--; $j--; +} +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +} +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) { + $res = @include "../main.inc.php"; +} +if (!$res && file_exists("../../main.inc.php")) { + $res = @include "../../main.inc.php"; +} +if (!$res && file_exists("../../../main.inc.php")) { + $res = @include "../../../main.inc.php"; +} +if (!$res && file_exists("../../../../main.inc.php")) { + $res = @include "../../../../main.inc.php"; +} +if (!$res) { + die("Include of main fails"); +} + +require_once DOL_DOCUMENT_ROOT . '/core/class/html.formcompany.class.php'; +require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php'; +require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php'; +if (!empty($conf->categorie->enabled)) { + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcategory.class.php'; + require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; +} + +// load dolisirh libraries +require_once __DIR__ . '/../../class/timesheet.class.php'; + +// for other modules +//dol_include_once('/othermodule/class/otherobject.class.php'); + +// Load translation files required by the page +$langs->loadLangs(array("dolisirh@dolisirh", "other")); + +$action = GETPOST('action', 'aZ09') ?GETPOST('action', 'aZ09') : 'view'; // The action 'add', 'create', 'edit', 'update', 'view', ... +$massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists) +$show_files = GETPOST('show_files', 'int'); // Show files area generated by bulk actions ? +$confirm = GETPOST('confirm', 'alpha'); // Result of a confirmation +$cancel = GETPOST('cancel', 'alpha'); // We click on a Cancel button +$toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected into a list +$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'timesheetlist'; // To manage different context of search +$backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page +$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print') + +$id = GETPOST('id', 'int'); + +// Load variable for pagination +$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); +$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); +if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) { + // If $page is not defined, or '' or -1 or if we click on clear filters + $page = 0; +} +$offset = $limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; + +if (!empty($conf->categorie->enabled)) { + $search_category_array = GETPOST("search_category_timesheet_list", "array"); +} + +// Initialize technical objects +$object = new TimeSheet($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction = $conf->dolisirh->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('timesheetlist')); // Note that conf->hooks_modules contains array + +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); +//$extrafields->fetch_name_optionals_label($object->table_element_line); + +$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); + +// Default sort order (if not yet defined by previous GETPOST) +if (!$sortfield) { + reset($object->fields); // Reset is required to avoid key() to return null. + $sortfield = "t.".key($object->fields); // Set here default search field. By default 1st field in definition. +} +if (!$sortorder) { + $sortorder = "ASC"; +} + +// Initialize array of search criterias +$search_all = GETPOST('search_all', 'alphanohtml'); +$search = array(); +foreach ($object->fields as $key => $val) { + if (GETPOST('search_'.$key, 'alpha') !== '') { + $search[$key] = GETPOST('search_'.$key, 'alpha'); + } + if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) { + $search[$key.'_dtstart'] = dol_mktime(0, 0, 0, GETPOST('search_'.$key.'_dtstartmonth', 'int'), GETPOST('search_'.$key.'_dtstartday', 'int'), GETPOST('search_'.$key.'_dtstartyear', 'int')); + $search[$key.'_dtend'] = dol_mktime(23, 59, 59, GETPOST('search_'.$key.'_dtendmonth', 'int'), GETPOST('search_'.$key.'_dtendday', 'int'), GETPOST('search_'.$key.'_dtendyear', 'int')); + } +} + +// List of fields to search into when doing a "search in all" +$fieldstosearchall = array(); +foreach ($object->fields as $key => $val) { + if (!empty($val['searchall'])) { + $fieldstosearchall['t.'.$key] = $val['label']; + } +} + +// Definition of array of fields for columns +$arrayfields = array(); +foreach ($object->fields as $key => $val) { + // If $val['visible']==0, then we never show the field + if (!empty($val['visible'])) { + $visible = (int) dol_eval($val['visible'], 1); + $arrayfields['t.'.$key] = array( + 'label'=>$val['label'], + 'checked'=>(($visible < 0) ? 0 : 1), + 'enabled'=>($visible != 3 && dol_eval($val['enabled'], 1)), + 'position'=>$val['position'], + 'help'=> isset($val['help']) ? $val['help'] : '' + ); + } +} +// Extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php'; + +$object->fields = dol_sort_array($object->fields, 'position'); +$arrayfields = dol_sort_array($arrayfields, 'position'); + +// There is several ways to check permission. +// Set $enablepermissioncheck to 1 to enable a minimum low level of checks +$enablepermissioncheck = 0; +if ($enablepermissioncheck) { + $permissiontoread = $user->rights->dolisirh->timesheet->read; + $permissiontoadd = $user->rights->dolisirh->timesheet->write; + $permissiontodelete = $user->rights->dolisirh->timesheet->delete; +} else { + $permissiontoread = 1; + $permissiontoadd = 1; + $permissiontodelete = 1; +} + +// Security check (enable the most restrictive one) +if ($user->socid > 0) accessforbidden(); +//if ($user->socid > 0) accessforbidden(); +//$socid = 0; if ($user->socid > 0) $socid = $user->socid; +//$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); +//restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); +if (empty($conf->dolisirh->enabled)) accessforbidden('Moule not enabled'); +if (!$permissiontoread) accessforbidden(); + + + +/* + * Actions + */ + +if (GETPOST('cancel', 'alpha')) { + $action = 'list'; + $massaction = ''; +} +if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { + $massaction = ''; +} + +$parameters = array(); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} + +if (empty($reshook)) { + // Selection of new fields + include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php'; + + // Purge search criteria + if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers + foreach ($object->fields as $key => $val) { + $search[$key] = ''; + if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) { + $search[$key.'_dtstart'] = ''; + $search[$key.'_dtend'] = ''; + } + } + $toselect = array(); + $search_array_options = array(); + $search_category_array = array(); + } + if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha') + || GETPOST('button_search_x', 'alpha') || GETPOST('button_search.x', 'alpha') || GETPOST('button_search', 'alpha')) { + $massaction = ''; // Protection to avoid mass action if we force a new search during a mass action confirmation + } + + // Mass actions + $objectclass = 'TimeSheet'; + $objectlabel = 'TimeSheet'; + $uploaddir = $conf->dolisirh->dir_output; + include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; +} + + + +/* + * View + */ + +$form = new Form($db); + +$now = dol_now(); + +//$help_url="EN:Module_TimeSheet|FR:Module_TimeSheet_FR|ES:Módulo_TimeSheet"; +$help_url = ''; +$title = $langs->trans('TimeSheetList'); +$morejs = array("/dolisirh/js/dolisirh.js.php"); +$morecss = array("/dolisirh/css/dolisirh.css"); + + +// Build and execute select +// -------------------------------------------------------------------- +$sql = 'SELECT '; +$sql .= $object->getFieldList('t'); +// Add fields from extrafields +if (!empty($extrafields->attributes[$object->table_element]['label'])) { + foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { + $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key." as options_".$key : ''); + } +} +// Add fields from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= preg_replace('/^,/', '', $hookmanager->resPrint); +$sql = preg_replace('/,\s*$/', '', $sql); +$sql .= " FROM ".MAIN_DB_PREFIX.$object->table_element." as t"; +if (isset($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) { + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (t.rowid = ef.fk_object)"; +} +// Add table from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; +if ($object->ismultientitymanaged == 1) { + $sql .= " WHERE t.entity IN (".getEntity($object->element).")"; +} else { + $sql .= " WHERE 1 = 1"; +} +foreach ($search as $key => $val) { + if (array_key_exists($key, $object->fields)) { + if ($key == 'status' && $search[$key] == -1) { + continue; + } + $mode_search = (($object->isInt($object->fields[$key]) || $object->isFloat($object->fields[$key])) ? 1 : 0); + if ((strpos($object->fields[$key]['type'], 'integer:') === 0) || (strpos($object->fields[$key]['type'], 'sellist:') === 0) || !empty($object->fields[$key]['arrayofkeyval'])) { + if ($search[$key] == '-1' || ($search[$key] === '0' && (empty($object->fields[$key]['arrayofkeyval']) || !array_key_exists('0', $object->fields[$key]['arrayofkeyval'])))) { + $search[$key] = ''; + } + $mode_search = 2; + } + if ($search[$key] != '') { + $sql .= natural_search($key, $search[$key], (($key == 'status') ? 2 : $mode_search)); + } + } else { + if (preg_match('/(_dtstart|_dtend)$/', $key) && $search[$key] != '') { + $columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key); + if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) { + if (preg_match('/_dtstart$/', $key)) { + $sql .= " AND t.".$columnName." >= '".$db->idate($search[$key])."'"; + } + if (preg_match('/_dtend$/', $key)) { + $sql .= " AND t." . $columnName . " <= '" . $db->idate($search[$key]) . "'"; + } + } + } + } +} +if ($search_all) { + $sql .= natural_search(array_keys($fieldstosearchall), $search_all); +} + +if (!empty($conf->categorie->enabled)) { + $sql .= Categorie::getFilterSelectQuery('timesheet', "t.rowid", $search_category_array); +} + +//$sql.= dolSqlDateFilter("t.field", $search_xxxday, $search_xxxmonth, $search_xxxyear); +// Add where from extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; +// Add where from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; + +/* If a group by is required +$sql .= " GROUP BY "; +foreach($object->fields as $key => $val) { + $sql .= "t.".$key.", "; +} +// Add fields from extrafields +if (!empty($extrafields->attributes[$object->table_element]['label'])) { + foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { + $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key.', ' : ''); + } +} +// Add where from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListGroupBy', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; +$sql = preg_replace('/,\s*$/', '', $sql); +*/ + +// Add HAVING from hooks +/* +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListHaving', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= empty($hookmanager->resPrint) ? "" : " HAVING 1=1 ".$hookmanager->resPrint; +*/ + +// Count total nb of records +$nbtotalofrecords = ''; +if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { + /* This old and fast method to get and count full list returns all record so use a high amount of memory. + $resql = $db->query($sql); + $nbtotalofrecords = $db->num_rows($resql); + */ + /* The slow method does not consume memory on mysql (not tested on pgsql) */ + /*$resql = $db->query($sql, 0, 'auto', 1); + while ($db->fetch_object($resql)) { + $nbtotalofrecords++; + }*/ + /* The fast and low memory method to get and count full list converts the sql into a sql count */ + $sqlforcount = preg_replace('/^SELECT[a-z0-9\._\s\(\),]+FROM/i', 'SELECT COUNT(*) as nbtotalofrecords FROM', $sql); + $resql = $db->query($sqlforcount); + $objforcount = $db->fetch_object($resql); + $nbtotalofrecords = $objforcount->nbtotalofrecords; + if (($page * $limit) > $nbtotalofrecords) { // if total of record found is smaller than page * limit, goto and load page 0 + $page = 0; + $offset = 0; + } + $db->free($resql); +} + +// Complete request and execute it with limit +$sql .= $db->order($sortfield, $sortorder); +if ($limit) { + $sql .= $db->plimit($limit + 1, $offset); +} + +$resql = $db->query($sql); +if (!$resql) { + dol_print_error($db); + exit; +} + +$num = $db->num_rows($resql); + + +// Direct jump if only one record found +if ($num == 1 && !empty($conf->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE) && $search_all && !$page) { + $obj = $db->fetch_object($resql); + $id = $obj->rowid; + header("Location: ".dol_buildpath('/dolisirh/view/timesheet/timesheet_card.php', 1).'?id='.$id); + exit; +} + + +// Output page +// -------------------------------------------------------------------- + +llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', ''); + +// Example : Adding jquery code +// print ''; + +$arrayofselected = is_array($toselect) ? $toselect : array(); + +$param = ''; +if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { + $param .= '&contextpage='.urlencode($contextpage); +} +if ($limit > 0 && $limit != $conf->liste_limit) { + $param .= '&limit='.urlencode($limit); +} +foreach ($search as $key => $val) { + if (is_array($search[$key]) && count($search[$key])) { + foreach ($search[$key] as $skey) { + if ($skey != '') { + $param .= '&search_'.$key.'[]='.urlencode($skey); + } + } + } elseif ($search[$key] != '') { + $param .= '&search_'.$key.'='.urlencode($search[$key]); + } +} +if ($optioncss != '') { + $param .= '&optioncss='.urlencode($optioncss); +} +// Add $param from extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; +// Add $param from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object); // Note that $action and $object may have been modified by hook +$param .= $hookmanager->resPrint; + +// List of mass actions available +$arrayofmassactions = array( + //'validate'=>img_picto('', 'check', 'class="pictofixedwidth"').$langs->trans("Validate"), + //'generate_doc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("ReGeneratePDF"), + //'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"), + //'presend'=>img_picto('', 'email', 'class="pictofixedwidth"').$langs->trans("SendByMail"), +); +if ($permissiontodelete) { + $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); +} +if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete'))) { + $arrayofmassactions = array(); +} +$massactionbutton = $form->selectMassAction('', $arrayofmassactions); + +print '
'."\n"; +if ($optioncss != '') { + print ''; +} +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +$newcardbutton = dolGetButtonTitle($langs->trans('New'), '', 'fa fa-plus-circle', dol_buildpath('/dolisirh/view/timesheet/timesheet_card.php', 1).'?action=create', '', $permissiontoadd); + +print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'dolisirh32px@dolisirh', 0, $newcardbutton, '', $limit, 0, 0, 1); + +// Add code for pre mass action (confirmation or email presend form) +$topicmail = "SendTimeSheetRef"; +$modelmail = "timesheet"; +$objecttmp = new TimeSheet($db); +$trackid = 'xxxx'.$object->id; +include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; + +if ($search_all) { + $setupstring = ''; + foreach ($fieldstosearchall as $key => $val) { + $fieldstosearchall[$key] = $langs->trans($val); + $setupstring .= $key."=".$val.";"; + } + print ''."\n"; + print '
'.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
'."\n"; +} + +$moreforfilter = ''; +/*$moreforfilter.='
'; +$moreforfilter.= $langs->trans('MyFilter') . ': '; +$moreforfilter.= '
';*/ + +// Filter on categories +if (!empty($conf->categorie->enabled) && $user->rights->categorie->lire) { + $formcategory = new FormCategory($db); + $moreforfilter .= $formcategory->getFilterBox('timesheet', $search_category_array); +} + +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook +if (empty($reshook)) { + $moreforfilter .= $hookmanager->resPrint; +} else { + $moreforfilter = $hookmanager->resPrint; +} + +if (!empty($moreforfilter)) { + print '
'; + print $moreforfilter; + print '
'; +} + +$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; +$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields +$selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : ''); + +print '
'; // You can use div-table-responsive-no-min if you dont need reserved height for your table +print ''."\n"; + + +// Fields title search +// -------------------------------------------------------------------- +print ''; +foreach ($object->fields as $key => $val) { + $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); + if ($key == 'status') { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } elseif (in_array($val['type'], array('timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { + $cssforfield .= ($cssforfield ? ' ' : '').'right'; + } + if (!empty($arrayfields['t.'.$key]['checked'])) { + print ''; + } +} +// Extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; + +// Fields from hook +$parameters = array('arrayfields'=>$arrayfields); +$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; +// Action column +print ''; +print ''."\n"; + + +// Fields title label +// -------------------------------------------------------------------- +print ''; +foreach ($object->fields as $key => $val) { + $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); + if ($key == 'status') { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } elseif (in_array($val['type'], array('timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { + $cssforfield .= ($cssforfield ? ' ' : '').'right'; + } + if (!empty($arrayfields['t.'.$key]['checked'])) { + print getTitleFieldOfList($arrayfields['t.'.$key]['label'], 0, $_SERVER['PHP_SELF'], 't.'.$key, '', $param, ($cssforfield ? 'class="'.$cssforfield.'"' : ''), $sortfield, $sortorder, ($cssforfield ? $cssforfield.' ' : ''))."\n"; + } +} +// Extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; +// Hook fields +$parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder); +$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; +// Action column +print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n"; +print ''."\n"; + + +// Detect if we need a fetch on each output line +$needToFetchEachLine = 0; +if (isset($extrafields->attributes[$object->table_element]['computed']) && is_array($extrafields->attributes[$object->table_element]['computed']) && count($extrafields->attributes[$object->table_element]['computed']) > 0) { + foreach ($extrafields->attributes[$object->table_element]['computed'] as $key => $val) { + if (preg_match('/\$object/', $val)) { + $needToFetchEachLine++; // There is at least one compute field that use $object + } + } +} + + +// Loop on record +// -------------------------------------------------------------------- +$i = 0; +$totalarray = array(); +$totalarray['nbfield'] = 0; +while ($i < ($limit ? min($num, $limit) : $num)) { + $obj = $db->fetch_object($resql); + if (empty($obj)) { + break; // Should not happen + } + + // Store properties in $object + $object->setVarsFromFetchObj($obj); + + // Show here line of result + print ''; + foreach ($object->fields as $key => $val) { + $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); + if (in_array($val['type'], array('date', 'datetime', 'timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } elseif ($key == 'status') { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } + + if (in_array($val['type'], array('timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + } elseif ($key == 'ref') { + $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + } + + if (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('rowid', 'status')) && empty($val['arrayofkeyval'])) { + $cssforfield .= ($cssforfield ? ' ' : '').'right'; + } + //if (in_array($key, array('fk_soc', 'fk_user', 'fk_warehouse'))) $cssforfield = 'tdoverflowmax100'; + + if (!empty($arrayfields['t.'.$key]['checked'])) { + print ''; + if ($key == 'status') { + print $object->getLibStatut(5); + } elseif ($key == 'rowid') { + print $object->showOutputField($val, $key, $object->id, ''); + } else { + print $object->showOutputField($val, $key, $object->$key, ''); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + if (!empty($val['isameasure']) && $val['isameasure'] == 1) { + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = 't.'.$key; + } + if (!isset($totalarray['val'])) { + $totalarray['val'] = array(); + } + if (!isset($totalarray['val']['t.'.$key])) { + $totalarray['val']['t.'.$key] = 0; + } + $totalarray['val']['t.'.$key] += $object->$key; + } + } + } + // Extra fields + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; + // Fields from hook + $parameters = array('arrayfields'=>$arrayfields, 'object'=>$object, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); + $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + // Action column + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + + print ''."\n"; + + $i++; +} + +// Show total line +include DOL_DOCUMENT_ROOT.'/core/tpl/list_print_total.tpl.php'; + +// If no record found +if ($num == 0) { + $colspan = 1; + foreach ($arrayfields as $key => $val) { + if (!empty($val['checked'])) { + $colspan++; + } + } + print ''; +} + + +$db->free($resql); + +$parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql); +$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; + +print '
'; + if (!empty($val['arrayofkeyval']) && is_array($val['arrayofkeyval'])) { + print $form->selectarray('search_'.$key, $val['arrayofkeyval'], (isset($search[$key]) ? $search[$key] : ''), $val['notnull'], 0, 0, '', 1, 0, 0, '', 'maxwidth100', 1); + } elseif ((strpos($val['type'], 'integer:') === 0) || (strpos($val['type'], 'sellist:') === 0)) { + print $object->showInputField($val, $key, (isset($search[$key]) ? $search[$key] : ''), '', '', 'search_', 'maxwidth125', 1); + } elseif (preg_match('/^(date|timestamp|datetime)/', $val['type'])) { + print '
'; + print $form->selectDate($search[$key.'_dtstart'] ? $search[$key.'_dtstart'] : '', "search_".$key."_dtstart", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From')); + print '
'; + print '
'; + print $form->selectDate($search[$key.'_dtend'] ? $search[$key.'_dtend'] : '', "search_".$key."_dtend", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to')); + print '
'; + } elseif ($key == 'lang') { + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; + $formadmin = new FormAdmin($db); + print $formadmin->select_language($search[$key], 'search_lang', 0, null, 1, 0, 0, 'minwidth150 maxwidth200', 2); + } else { + print ''; + } + print '
'; +$searchpicto = $form->showFilterButtons(); +print $searchpicto; +print '
'; + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($object->id, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print '
'.$langs->trans("NoRecordFound").'
'."\n"; +print '
'."\n"; + +print '
'."\n"; + +if (in_array('builddoc', $arrayofmassactions) && ($nbtotalofrecords === '' || $nbtotalofrecords)) { + $hidegeneratedfilelistifempty = 1; + if ($massaction == 'builddoc' || $action == 'remove_file' || $show_files) { + $hidegeneratedfilelistifempty = 0; + } + + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; + $formfile = new FormFile($db); + + // Show list of available documents + $urlsource = $_SERVER['PHP_SELF'].'?sortfield='.$sortfield.'&sortorder='.$sortorder; + $urlsource .= str_replace('&', '&', $param); + + $filedir = $diroutputmassaction; + $genallowed = $permissiontoread; + $delallowed = $permissiontoadd; + + print $formfile->showdocuments('massfilesarea_dolisirh', '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty); +} + +// End of page +llxFooter(); +$db->close(); diff --git a/view/timesheet/timesheet_note.php b/view/timesheet/timesheet_note.php new file mode 100644 index 0000000..3ea4f4a --- /dev/null +++ b/view/timesheet/timesheet_note.php @@ -0,0 +1,212 @@ + + * Copyright (C) ---Put here your own copyright and developer email--- + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file timesheet_note.php + * \ingroup dolisirh + * \brief Tab for notes on TimeSheet + */ + +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Do not create database handler $db +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Do not load object $user +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); // Do not load object $mysoc +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1'); // Do not load object $langs +//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION', '1'); // Do not check injection attack on GET parameters +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION', '1'); // Do not check injection attack on POST parameters +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK', '1'); // Do not check CSRF attack (test on referer + on token if option MAIN_SECURITY_CSRF_WITH_TOKEN is on). +//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on) +//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK', '1'); // Do not check style html tag into posted data +//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu +//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php +//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library +//if (! defined("NOLOGIN")) define("NOLOGIN", '1'); // If this page is public (can be called outside logged session). This include the NOIPCHECK too. +//if (! defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip +//if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT', 'auto'); // Force lang to a particular value +//if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule'); // Force authentication handler +//if (! defined("NOREDIRECTBYMAINTOLOGIN")) define('NOREDIRECTBYMAINTOLOGIN', 1); // The main.inc.php does not make a redirect if not logged, instead show simple error message +//if (! defined("FORCECSP")) define('FORCECSP', 'none'); // Disable all Content Security Policies +//if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET +//if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) { + $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"; +} +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { + $i--; $j--; +} +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1))."/main.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php"; +} +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) { + $res = @include "../main.inc.php"; +} +if (!$res && file_exists("../../main.inc.php")) { + $res = @include "../../main.inc.php"; +} +if (!$res && file_exists("../../../main.inc.php")) { + $res = @include "../../../main.inc.php"; +} +if (!$res && file_exists("../../../../main.inc.php")) { + $res = @include "../../../../main.inc.php"; +} +if (!$res) { + die("Include of main fails"); +} + +require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; + +dol_include_once('/dolisirh/class/timesheet.class.php'); +dol_include_once('/dolisirh/lib/dolisirh_timesheet.lib.php'); + +// Load translation files required by the page +$langs->loadLangs(array("dolisirh@dolisirh", "companies")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'aZ09'); +$cancel = GETPOST('cancel', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +// Initialize technical objects +$object = new TimeSheet($db); +$extrafields = new ExtraFields($db); +$project = new Project($db); +$diroutputmassaction = $conf->dolisirh->dir_output.'/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('timesheetnote', 'globalcard')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals +if ($id > 0 || !empty($ref)) { + $upload_dir = $conf->dolisirh->multidir_output[!empty($object->entity) ? $object->entity : $conf->entity]."/".$object->id; +} + + +// There is several ways to check permission. +// Set $enablepermissioncheck to 1 to enable a minimum low level of checks +$enablepermissioncheck = 0; +if ($enablepermissioncheck) { + $permissiontoread = $user->rights->dolisirh->timesheet->read; + $permissiontoadd = $user->rights->dolisirh->timesheet->write; + $permissionnote = $user->rights->dolisirh->timesheet->write; // Used by the include of actions_setnotes.inc.php +} else { + $permissiontoread = 1; + $permissiontoadd = 1; + $permissionnote = 1; +} + +// Security check (enable the most restrictive one) +//if ($user->socid > 0) accessforbidden(); +//if ($user->socid > 0) $socid = $user->socid; +//$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0); +//restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft); +if (empty($conf->dolisirh->enabled)) accessforbidden(); +if (!$permissiontoread) accessforbidden(); + + +/* + * Actions + */ + +$parameters = array(); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} +if (empty($reshook)) { + include DOL_DOCUMENT_ROOT.'/core/actions_setnotes.inc.php'; // Must be include, not include_once +} + + +/* + * View + */ + +$form = new Form($db); + +//$help_url='EN:Customers_Orders|FR:Commandes_Clients|ES:Pedidos de clientes'; +$help_url = ''; +$morejs = array("/dolisirh/js/dolisirh.js.php"); +$morecss = array("/dolisirh/css/dolisirh.css"); + +llxHeader('', $langs->trans('TimeSheet'), $help_url, '', 0, 0, $morejs, $morecss); + +if ($id > 0 || !empty($ref)) { + $object->fetch_thirdparty(); + + $head = timesheetPrepareHead($object); + + print dol_get_fiche_head($head, 'note', $langs->trans("TimeSheet"), -1, 'dolisirh@dolisirh'); + + // Object card + // ------------------------------------------------------------ + $linkback = ''.$langs->trans("BackToList").''; + + $morehtmlref = '
'; + // Thirdparty + if (! empty($conf->societe->enabled)) { + $object->fetch_thirdparty(); + $morehtmlref .= $langs->trans('ThirdParty') . ' : ' . (is_object($object->thirdparty) ? $object->thirdparty->getNomUrl(1) : ''); + } + // Project + if (! empty($conf->projet->enabled)) { + $langs->load("projects"); + $morehtmlref .= '
' . $langs->trans('Project') . ' '; + if (! empty($object->fk_project)) { + $project->fetch($object->fk_project); + $morehtmlref .= ': ' . $project->getNomUrl(1, '', 1); + } else { + $morehtmlref .= ''; + } + } + $morehtmlref .= '
'; + + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + + print '
'; + print '
'; + + + $cssclass = "titlefield"; + + if ($object->status >= $object::STATUS_VALIDATED) { + $permissionnote = 0; + } + include DOL_DOCUMENT_ROOT.'/core/tpl/notes.tpl.php'; + + print '
'; + + print dol_get_fiche_end(); +} + +// End of page +llxFooter(); +$db->close(); diff --git a/view/timespent_day.php b/view/timespent_day.php new file mode 100644 index 0000000..13dd694 --- /dev/null +++ b/view/timespent_day.php @@ -0,0 +1,924 @@ + + * Copyright (C) 2004-2016 Laurent Destailleur + * Copyright (C) 2005-2010 Regis Houssin + * Copyright (C) 2010 François Legastelois + * Copyright (C) 2018 Frédéric France + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/projet/activity/perday.php + * \ingroup projet + * \brief List activities of tasks (per day entry) + */ + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if ( ! $res && ! empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"] . "/main.inc.php"; +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } +if ( ! $res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1)) . "/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1)) . "/main.inc.php"; +if ( ! $res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1))) . "/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1))) . "/main.inc.php"; +// Try main.inc.php using relative path +if ( ! $res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; +if ( ! $res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; +if ( ! $res) die("Include of main fails"); + +require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; +require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; +require_once DOL_DOCUMENT_ROOT.'/holiday/class/holiday.class.php'; +if (!empty($conf->categorie->enabled)) { + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcategory.class.php'; + require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; +} + +require_once DOL_DOCUMENT_ROOT.'/custom/dolisirh/lib/dolisirh_function.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/custom/dolisirh/class/workinghours.class.php'; + +global $conf, $user, $langs, $db; + +// Load translation files required by the page +$langs->loadLangs(array('projects', 'users', 'companies')); + +$action = GETPOST('action', 'aZ09'); +$mode = GETPOST("mode", 'alpha'); +$id = GETPOST('id', 'int'); +$taskid = GETPOST('taskid', 'int'); + +$contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'perdaycard'; + +$mine = 0; +if ($mode == 'mine') { + $mine = 1; +} + +$projectid = GETPOSTISSET("id") ? GETPOST("id", "int", 1) : GETPOST("projectid", "int"); + +$hookmanager->initHooks(array('timesheetperdaycard')); + +// Security check +$socid = 0; +// For external user, no check is done on company because readability is managed by public status of project and assignement. +//if ($user->socid > 0) $socid=$user->socid; +$result = restrictedArea($user, 'projet', $projectid); + +$now = dol_now(); + +$year = GETPOST('reyear', 'int') ?GETPOST('reyear', 'int') : (GETPOST("year", "int") ?GETPOST("year", "int") : (GETPOST("addtimeyear", "int") ?GETPOST("addtimeyear", "int") : date("Y"))); +$month = GETPOST('remonth', 'int') ?GETPOST('remonth', 'int') : (GETPOST("month", "int") ?GETPOST("month", "int") : (GETPOST("addtimemonth", "int") ?GETPOST("addtimemonth", "int") : date("m"))); +$day = GETPOST('reday', 'int') ?GETPOST('reday', 'int') : (GETPOST("day", "int") ?GETPOST("day", "int") : (GETPOST("addtimeday", "int") ?GETPOST("addtimeday", "int") : date("d"))); +$week = GETPOST("week", "int") ?GETPOST("week", "int") : date("W"); + +$day = (int) $day; + +//$search_categ = GETPOST("search_categ", 'alpha'); +$search_usertoprocessid = GETPOST('search_usertoprocessid', 'int'); +$search_task_ref = GETPOST('search_task_ref', 'alpha'); +$search_task_label = GETPOST('search_task_label', 'alpha'); +$search_project_ref = GETPOST('search_project_ref', 'alpha'); +$search_thirdparty = GETPOST('search_thirdparty', 'alpha'); +$search_declared_progress = GETPOST('search_declared_progress', 'alpha'); +if (!empty($conf->categorie->enabled)) { + $search_category_array = GETPOST("search_category_".Categorie::TYPE_PROJECT."_list", "array"); +} + + +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); + +$monthofday = GETPOST('addtimemonth'); +$dayofday = GETPOST('addtimeday'); +$yearofday = GETPOST('addtimeyear'); + +/*var_dump(GETPOST('remonth')); +var_dump(GETPOST('button_search_x')); +var_dump(GETPOST('button_addtime'));*/ + +$daytoparse = $now; +if ($year && $month && $day) { + $daytoparse = dol_mktime(0, 0, 0, $month, $day, $year); // this are value submited after submit of action 'submitdateselect' +} elseif ($yearofday && $monthofday && $dayofday) { + $daytoparse = dol_mktime(0, 0, 0, $monthofday, $dayofday, $yearofday); // xxxofday is value of day after submit action 'addtime' +} + +$daytoparsegmt = dol_now('gmt'); +if ($yearofday && $monthofday && $dayofday) $daytoparsegmt = dol_mktime(0, 0, 0, $monthofday, $dayofday, $yearofday, 'gmt'); // xxxofday is value of day after submit action 'addtime' +elseif ($year && $month && $day) $daytoparsegmt = dol_mktime(0, 0, 0, $month, $day, $year, 'gmt'); // this are value submited after submit of action 'submitdateselect' + +if (empty($search_usertoprocessid) || $search_usertoprocessid == $user->id) { + $usertoprocess = $user; + $search_usertoprocessid = $usertoprocess->id; +} elseif ($search_usertoprocessid > 0) { + $usertoprocess = new User($db); + $usertoprocess->fetch($search_usertoprocessid); + $search_usertoprocessid = $usertoprocess->id; +} else { + $usertoprocess = new User($db); +} + +$object = new Task($db); +$project = new Project($db); +$workinghours = new WorkingHours($db); + +$current_workinghours = $workinghours->fetchCurrentWorkingHours($user->id, 'user'); + +// Extra fields +$extrafields = new ExtraFields($db); + +// fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +// Definition of fields for list +$arrayfields = array(); +$arrayfields['t.planned_workload'] = array('label'=>'PlannedWorkload', 'checked'=>1, 'enabled'=>1, 'position'=>0); +$arrayfields['t.progress'] = array('label'=>'ProgressDeclared', 'checked'=>1, 'enabled'=>1, 'position'=>0); +$arrayfields['timeconsumed'] = array('label'=>'TimeConsumed', 'checked'=>1, 'enabled'=>1, 'position'=>15); +/*$arrayfields=array( + // Project + 'p.opp_amount'=>array('label'=>$langs->trans("OpportunityAmountShort"), 'checked'=>0, 'enabled'=>($conf->global->PROJECT_USE_OPPORTUNITIES?1:0), 'position'=>103), + 'p.fk_opp_status'=>array('label'=>$langs->trans("OpportunityStatusShort"), 'checked'=>0, 'enabled'=>($conf->global->PROJECT_USE_OPPORTUNITIES?1:0), 'position'=>104), + 'p.opp_percent'=>array('label'=>$langs->trans("OpportunityProbabilityShort"), 'checked'=>0, 'enabled'=>($conf->global->PROJECT_USE_OPPORTUNITIES?1:0), 'position'=>105), + 'p.budget_amount'=>array('label'=>$langs->trans("Budget"), 'checked'=>0, 'position'=>110), + 'p.usage_bill_time'=>array('label'=>$langs->trans("BillTimeShort"), 'checked'=>0, 'position'=>115), + ); + */ +// Extra fields +if (!empty($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label']) > 0) { + foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) { + if (!empty($extrafields->attributes[$object->table_element]['list'][$key])) { + $arrayfields["efpt.".$key] = array('label'=>$extrafields->attributes[$object->table_element]['label'][$key], 'checked'=>(($extrafields->attributes[$object->table_element]['list'][$key] < 0) ? 0 : 1), 'position'=>$extrafields->attributes[$object->table_element]['pos'][$key], 'enabled'=>(abs((int) $extrafields->attributes[$object->table_element]['list'][$key]) != 3 && $extrafields->attributes[$object->table_element]['perms'][$key])); + } + } +} +$arrayfields = dol_sort_array($arrayfields, 'position'); + + +$search_array_options_project = $extrafields->getOptionalsFromPost($project->table_element, '', 'search_'); +$search_array_options_task = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_task_'); + + +/* + * Actions + */ + +$parameters = array('id' => $id, 'taskid' => $taskid, 'projectid' => $projectid); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} +// Purge criteria +if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers + $action = ''; + //$search_categ = ''; + $search_usertoprocessid = $user->id; + $search_task_ref = ''; + $search_task_label = ''; + $search_project_ref = ''; + $search_thirdparty = ''; + $search_declared_progress = ''; + + $search_array_options_project = array(); + $search_array_options_task = array(); + $search_category_array = array(); + + // We redefine $usertoprocess + $usertoprocess = $user; +} +if (GETPOST("button_search_x", 'alpha') || GETPOST("button_search.x", 'alpha') || GETPOST("button_search", 'alpha')) { + $action = ''; +} + +if (GETPOST('submitdateselect')) { + if (GETPOST('remonth', 'int') && GETPOST('reday', 'int') && GETPOST('reyear', 'int')) { + $daytoparse = dol_mktime(0, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int')); + } + + $action = ''; +} + +include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php'; + +if ($action == 'addtime' && $user->rights->projet->lire && GETPOST('assigntask') && GETPOST('formfilteraction') != 'listafterchangingselectedfields') { + $action = 'assigntask'; + + if ($taskid > 0) { + $result = $object->fetch($taskid, $ref); + if ($result < 0) { + $error++; + } + } else { + setEventMessages($langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Task")), '', 'errors'); + $error++; + } + if (!GETPOST('type')) { + setEventMessages($langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), '', 'errors'); + $error++; + } + if (!$error) { + $idfortaskuser = $usertoprocess->id; + $result = $object->add_contact($idfortaskuser, GETPOST("type"), 'internal'); + + if ($result >= 0 || $result == -2) { // Contact add ok or already contact of task + // Test if we are already contact of the project (should be rare but sometimes we can add as task contact without being contact of project, like when admin user has been removed from contact of project) + $sql = 'SELECT ec.rowid FROM '.MAIN_DB_PREFIX.'element_contact as ec, '.MAIN_DB_PREFIX.'c_type_contact as tc WHERE tc.rowid = ec.fk_c_type_contact'; + $sql .= ' AND ec.fk_socpeople = '.((int) $idfortaskuser)." AND ec.element_id = ".((int) $object->fk_project)." AND tc.element = 'project' AND source = 'internal'"; + $resql = $db->query($sql); + if ($resql) { + $obj = $db->fetch_object($resql); + if (!$obj) { // User is not already linked to project, so we will create link to first type + $project = new Project($db); + $project->fetch($object->fk_project); + // Get type + $listofprojcontact = $project->liste_type_contact('internal'); + + if (count($listofprojcontact)) { + $typeforprojectcontact = reset(array_keys($listofprojcontact)); + $result = $project->add_contact($idfortaskuser, $typeforprojectcontact, 'internal'); + } + } + } else { + dol_print_error($db); + } + } + } + + if ($result < 0) { + $error++; + if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') { + $langs->load("errors"); + setEventMessages($langs->trans("ErrorTaskAlreadyAssigned"), null, 'warnings'); + } else { + setEventMessages($object->error, $object->errors, 'errors'); + } + } + + if (!$error) { + setEventMessages("TaskAssignedToEnterTime", null); + $taskid = 0; + } + + $action = ''; +} + +if ($action == 'addtime' && $user->rights->projet->lire && GETPOST('formfilteraction') != 'listafterchangingselectedfields') { + $timespent_duration = array(); + if (is_array($_POST)) { + foreach ($_POST as $key => $time) { + if (intval($time) > 0) { + $matches = array(); + // Hours or minutes of duration + if (preg_match("/([0-9]+)duration(hour|min)/", $key, $matches)) { + $id = $matches[1]; + if ($id > 0) { + // We store HOURS in seconds + if ($matches[2] == 'hour') { + $timespent_duration[$id] += $time * 60 * 60; + } + + // We store MINUTES in seconds + if ($matches[2] == 'min') { + $timespent_duration[$id] += $time * 60; + } + } + } + } + } + } + + if (count($timespent_duration) > 0) { + $timespent_minutes = 0; + foreach($timespent_duration as $key => $val) { + $timespent_minutes += $val / 60; + } + if (!$conf->global->DOLISIRH_SPEND_MORE_TIME_THAN_PLANNED) { + if ($timespent_minutes > GETPOST('nonconsumedtime')) { + setEventMessages($langs->trans("TooMuchTimeSpent"), null, 'errors'); + header('Location: '.$_SERVER["PHP_SELF"].'?'.($projectid ? 'id='.$projectid : '').($search_usertoprocessid ? '&search_usertoprocessid='.urlencode($search_usertoprocessid) : '').($mode ? '&mode='.$mode : '').'&year='.$yearofday.'&month='.$monthofday.'&day='.$dayofday); + exit; + } + } + foreach ($timespent_duration as $key => $val) { + $object->fetch($key); + $taskid = $object->id; + + if (GETPOSTISSET($taskid.'progress')) { + $object->progress = GETPOST($taskid.'progress', 'int'); + } else { + unset($object->progress); + } + + $object->timespent_duration = $val; + $object->timespent_fk_user = $usertoprocess->id; + $object->timespent_note = GETPOST($key.'note'); + if (GETPOST($key."hour", 'int') != '' && GETPOST($key."hour", 'int') >= 0) { // If hour was entered + $object->timespent_datehour = dol_mktime(GETPOST($key."hour", 'int'), GETPOST($key."min", 'int'), 0, $monthofday, $dayofday, $yearofday); + $object->timespent_withhour = 1; + } else { + $object->timespent_datehour = dol_mktime(12, 0, 0, $monthofday, $dayofday, $yearofday); + } + $object->timespent_date = $object->timespent_datehour; + + if ($object->timespent_date > 0) { + $result = $object->addTimeSpent($user); + } else { + setEventMessages("ErrorBadDate", null, 'errors'); + $error++; + break; + } + + if ($result < 0) { + setEventMessages($object->error, $object->errors, 'errors'); + $error++; + break; + } + } + + if (!$error) { + setEventMessages($langs->trans("RecordSaved"), null, 'mesgs'); + + // Redirect to avoid submit twice on back + header('Location: '.$_SERVER["PHP_SELF"].'?'.($projectid ? 'id='.$projectid : '').($search_usertoprocessid ? '&search_usertoprocessid='.urlencode($search_usertoprocessid) : '').($mode ? '&mode='.$mode : '').'&year='.$yearofday.'&month='.$monthofday.'&day='.$dayofday); + exit; + } + } else { + setEventMessages($langs->trans("ErrorTimeSpentIsEmpty"), null, 'errors'); + } + +} + +if ($action == 'showOnlyFavoriteTasks') { + if ($conf->global->DOLISIRH_SHOW_ONLY_FAVORITE_TASKS == 1) { + dolibarr_set_const($db, 'DOLISIRH_SHOW_ONLY_FAVORITE_TASKS', 0, 'integer', 0, '', $conf->entity); + } else { + dolibarr_set_const($db, 'DOLISIRH_SHOW_ONLY_FAVORITE_TASKS', 1, 'integer', 0, '', $conf->entity); + } +} + + +/* + * View + */ + +$form = new Form($db); +$formother = new FormOther($db); +$formcompany = new FormCompany($db); +$formproject = new FormProjets($db); +$projectstatic = new Project($db); +$project = new Project($db); +$taskstatic = new Task($db); +$thirdpartystatic = new Societe($db); +$holiday = new Holiday($db); + +$prev = dol_getdate($daytoparse - (24 * 3600)); +$prev_year = $prev['year']; +$prev_month = $prev['mon']; +$prev_day = $prev['mday']; + +$next = dol_getdate($daytoparse + (24 * 3600)); +$next_year = $next['year']; +$next_month = $next['mon']; +$next_day = $next['mday']; + +$title = $langs->trans("TimeSpent"); +$help_url = ''; +$morejs = array("/dolisirh/js/dolisirh.js.php", "/core/js/timesheet.js"); +$morecss = array("/dolisirh/css/dolisirh.css"); + +$projectsListId = $projectstatic->getProjectsAuthorizedForUser($usertoprocess, (empty($usertoprocess->id) ? 2 : 0), 1); // Return all project i have permission on (assigned to me+public). I want my tasks and some of my task may be on a public projet that is not my project + +if ($id) { + $project->fetch($id); + $project->fetch_thirdparty(); +} + +if (GETPOST('year')) { + $year_post = GETPOST('year'); +} else if (GETPOST('reyear')) { + $year_post = GETPOST('reyear'); +} else if (GETPOST('addtimeyear')) { + $year_post = GETPOST('addtimeyear'); +} +if (GETPOST('month')) { + $month_post = GETPOST('month'); +} else if (GETPOST('remonth')) { + $month_post = GETPOST('remonth'); +} else if (GETPOST('addtimemonth')) { + $month_post = GETPOST('addtimemonth'); +} +if (GETPOST('day')) { + $day_post = GETPOST('day'); +} else if (GETPOST('reday')) { + $day_post = GETPOST('reday'); +} else if (GETPOST('addtimeday')) { + $day_post = GETPOST('addtimeday'); +} + +$wanted_date = $year_post ? $year_post . '-' . ($month_post > 9 ? $month_post : 0 . $month_post) . '-' . ($day_post > 9 ? $day_post : 0 . $day_post) : date("Y-m-d", dol_now()); +$today_workinghours = 'workinghours_' . strtolower(date("l", dol_strlen($wanted_date) > 0 ? strtotime($wanted_date) : dol_now())); + +$worked_hours = floor($current_workinghours->$today_workinghours / 60); +$worked_minutes = ($current_workinghours->$today_workinghours % 60); +$worked_minutes = $worked_minutes < 10 ? 0 . $worked_minutes : $worked_minutes; + +$today_consumed_time = $taskstatic->fetchAllTimeSpent($user, ' AND ptt.task_date = "' . $wanted_date . '"'); +$already_consumed_time = 0; +if (is_array($today_consumed_time) && !empty($today_consumed_time)) { + foreach ($today_consumed_time as $consumed_time) { + $already_consumed_time += $consumed_time->timespent_duration; + } +} + +$non_consumed_time = $current_workinghours->$today_workinghours - floor($already_consumed_time / 60); +$non_consumed_hours = floor($non_consumed_time / 60); +$non_consumed_minutes = ($non_consumed_time % 60); +$non_consumed_minutes = $non_consumed_minutes < 10 ? 0 . $non_consumed_minutes : $non_consumed_minutes; +$non_consumed_hours = $non_consumed_hours > 0 ? $non_consumed_hours : '00'; +$non_consumed_minutes = $non_consumed_minutes > 0 ? $non_consumed_minutes : '00'; + +$already_consumed_time = $already_consumed_time / 60; +$consumed_hours = floor($already_consumed_time / 60); +$consumed_minutes = $already_consumed_time % 60; +$consumed_minutes = $consumed_minutes < 10 ? 0 . $consumed_minutes : $consumed_minutes; +$consumed_hours = $consumed_hours > 0 ? $consumed_hours : '00'; +$consumed_minutes = $consumed_minutes > 0 ? $consumed_minutes : '00'; + +$onlyopenedproject = 1; // or -1 +$morewherefilter = ''; + +if ($search_project_ref) { + $morewherefilter .= natural_search(array("p.ref", "p.title"), $search_project_ref); +} +if ($search_task_ref) { + $morewherefilter .= natural_search("t.ref", $search_task_ref); +} +if ($search_task_label) { + $morewherefilter .= natural_search(array("t.ref", "t.label"), $search_task_label); +} +if ($search_thirdparty) { + $morewherefilter .= natural_search("s.nom", $search_thirdparty); +} +if ($search_declared_progress) { + $morewherefilter .= natural_search("t.progress", $search_declared_progress, 1); +} +if (!empty($conf->categorie->enabled)) { + $morewherefilter .= Categorie::getFilterSelectQuery(Categorie::TYPE_PROJECT, "p.rowid", $search_category_array); +} + +$sql = &$morewherefilter; + +/*$search_array_options = $search_array_options_project; +$extrafieldsobjectprefix='efp.'; +$search_options_pattern='search_options_'; +$extrafieldsobjectkey='projet'; +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; +*/ +$search_array_options = $search_array_options_task; +$extrafieldsobjectprefix = 'efpt.'; +$search_options_pattern = 'search_task_options_'; +$extrafieldsobjectkey = 'projet_task'; +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; + +$tasksarray = getFavoriteTasksArray($taskstatic->id, 0, 0, ($project->id ? $project->id : 0), $socid, 0, $search_project_ref, $onlyopenedproject, $morewherefilter, ($search_usertoprocessid ? $search_usertoprocessid : 0), 0, $extrafields); // We want to see all task of opened project i am allowed to see and that match filter, not only my tasks. Later only mine will be editable later. +if ($morewherefilter) { // Get all task without any filter, so we can show total of time spent for not visible tasks + $tasksarraywithoutfilter = getFavoriteTasksArray($taskstatic->id, 0, 0, ($project->id ? $project->id : 0), $socid, 0, '', $onlyopenedproject, '', ($search_usertoprocessid ? $search_usertoprocessid : 0)); // We want to see all task of opened project i am allowed to see and that match filter, not only my tasks. Later only mine will be editable later. +} + +$projectsrole = $taskstatic->getUserRolesForProjectsOrTasks($usertoprocess, 0, ($project->id ? $project->id : 0), 0, $onlyopenedproject); +$tasksrole = $taskstatic->getUserRolesForProjectsOrTasks(0, $usertoprocess, ($project->id ? $project->id : 0), 0, $onlyopenedproject); +//var_dump($usertoprocess); +//var_dump($projectsrole); +//var_dump($taskrole); + +llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss); + +//print_barre_liste($title, $page, $_SERVER["PHP_SELF"], "", $sortfield, $sortorder, "", $num, '', 'project'); + +$param = ''; +$param .= ($mode ? '&mode='.urlencode($mode) : ''); +$param .= ($search_project_ref ? '&search_project_ref='.urlencode($search_project_ref) : ''); +$param .= ($search_usertoprocessid > 0 ? '&search_usertoprocessid='.urlencode($search_usertoprocessid) : ''); +$param .= ($search_thirdparty ? '&search_thirdparty='.urlencode($search_thirdparty) : ''); +$param .= ($search_task_ref ? '&search_task_ref='.urlencode($search_task_ref) : ''); +$param .= ($search_task_label ? '&search_task_label='.urlencode($search_task_label) : ''); + +/* +$search_array_options = $search_array_options_project; +$search_options_pattern='search_options_'; +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; +*/ + +$search_array_options = $search_array_options_task; +$search_options_pattern = 'search_task_options_'; +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; + +// Show navigation bar +$nav = ''.img_previous($langs->trans("Previous"))."\n"; +$nav .= dol_print_date(dol_mktime(0, 0, 0, $month, $day, $year), "%A").' '; +$nav .= " ".dol_print_date(dol_mktime(0, 0, 0, $month, $day, $year), "day")." \n"; +$nav .= ''.img_next($langs->trans("Next"))."\n"; +$nav .= ' '.$form->selectDate(-1, '', 0, 0, 2, "addtime", 1, 1).' '; +$nav .= ' '; + +$picto = 'clock'; + +print '
id > 0 ? '?id='.$project->id : '').'">'; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +$tmp = dol_getdate($daytoparse); +print ''; +print ''; +print ''; + +$head = dolisirh_timesheet_prepare_head($mode, $usertoprocess); +print dol_get_fiche_head($head, 'inputperday', $langs->trans('TimeSpent'), -1, $picto); + +// Show description of content +print '
'; +if ($mine || ($usertoprocess->id == $user->id)) { + print $langs->trans("MyTasksDesc").'.'.($onlyopenedproject ? ' '.$langs->trans("OnlyOpenedProject") : '').'
'; +} else { + if (empty($usertoprocess->id) || $usertoprocess->id < 0) { + if ($user->rights->projet->all->lire && !$socid) { + print $langs->trans("ProjectsDesc").'.'.($onlyopenedproject ? ' '.$langs->trans("OnlyOpenedProject") : '').'
'; + } else { + print $langs->trans("ProjectsPublicTaskDesc").'.'.($onlyopenedproject ? ' '.$langs->trans("OnlyOpenedProject") : '').'
'; + } + } +} +if ($mine || ($usertoprocess->id == $user->id)) { + print $langs->trans("OnlyYourTaskAreVisible").'
'; +} else { + print $langs->trans("AllTaskVisibleButEditIfYouAreAssigned").'
'; +} +print '
'; + +print dol_get_fiche_end(); + + +print '
'.$nav.'
'; // We move this before the assign to components so, the default submit button is not the assign to. +// +//print '
'; +//$titleassigntask = $langs->transnoentities("AssignTaskToMe"); +//if ($usertoprocess->id != $user->id) { +// $titleassigntask = $langs->transnoentities("AssignTaskToUser", $usertoprocess->getFullName($langs)); +//} +//print '
'; +//print img_picto('', 'projecttask', 'class="pictofixedwidth"'); +//$formproject->selectTasks($socid ? $socid : -1, $taskid, 'taskid', 32, 0, '-- '.$langs->trans("ChooseANotYetAssignedTask").' --', 1, 0, 0, '', '', 'all', $usertoprocess); +//print '
'; +//print ' '; +//print $formcompany->selectTypeContact($object, '', 'type', 'internal', 'rowid', 0, 'maxwidth150onsmartphone'); +//print ''; +//print '
'; + +print '
'; +print $langs->trans('ShowOnlyFavoriteTasks'); +print 'global->DOLISIRH_SHOW_ONLY_FAVORITE_TASKS ? ' checked' : '').' >'; + +$moreforfilter = ''; + +// If the user can view user other than himself +$moreforfilter .= '
'; +$moreforfilter .= '
'; +$includeonly = 'hierarchyme'; +if (empty($user->rights->user->user->lire)) { + $includeonly = array($user->id); +} +$moreforfilter .= img_picto($langs->trans('Filter').' '.$langs->trans('User'), 'user', 'class="paddingright pictofixedwidth"').$form->select_dolusers($search_usertoprocessid ? $search_usertoprocessid : $usertoprocess->id, 'search_usertoprocessid', $user->rights->user->user->lire ? 0 : 0, null, 0, $includeonly, null, 0, 0, 0, '', 0, '', 'maxwidth200'); +$moreforfilter .= '
'; + +if (empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) { + $moreforfilter .= '
'; + $moreforfilter .= '
'; + $moreforfilter .= img_picto($langs->trans('Filter').' '.$langs->trans('Project'), 'project', 'class="paddingright pictofixedwidth"').''; + $moreforfilter .= '
'; + + $moreforfilter .= '
'; + $moreforfilter .= '
'; + $moreforfilter .= img_picto($langs->trans('Filter').' '.$langs->trans('ThirdParty'), 'company', 'class="paddingright pictofixedwidth"').''; + $moreforfilter .= '
'; +} + +// Filter on categories +if (!empty($conf->categorie->enabled) && $user->rights->categorie->lire) { + $formcategory = new FormCategory($db); + $moreforfilter .= $formcategory->getFilterBox(Categorie::TYPE_PROJECT, $search_category_array); +} + +if (!empty($moreforfilter)) { + print '
'; + print $moreforfilter; + $parameters = array(); + $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + print '
'; +} + +$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; +$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields + +// This must be after the $selectedfields +$addcolspan = 1; +if (!empty($arrayfields['timeconsumed']['checked'])) { + $addcolspan++; + $addcolspan++; +} +foreach ($arrayfields as $key => $val) { + if ($val['checked'] && substr($key, 0, 5) == 'efpt.') { + $addcolspan++; + } +} + +print '
'; +print ''."\n"; + +print ''; +if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) { + print ''; +} +if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) { + print ''; +} +print ''; +// TASK fields +$search_options_pattern = 'search_task_options_'; +$extrafieldsobjectkey = 'projet_task'; +$extrafieldsobjectprefix = 'efpt.'; +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; +print ''; +print ''; +if (!empty($arrayfields['timeconsumed']['checked'])) { + print ''; + print ''; +} +print ''; +//print ''; +//print ''; +// Action column +print ''; +print "\n"; + +print ''; +if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) { + print ''; +} +if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) { + print ''; +} +print ''; +// TASK fields +$extrafieldsobjectkey = 'projet_task'; +$extrafieldsobjectprefix = 'efpt.'; +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; +//if (!empty($arrayfields['t.planned_workload']['checked'])) { +// print ''; +//} +//if (!empty($arrayfields['t.progress']['checked'])) { +// print ''; +//} +if (!empty($arrayfields['timeconsumed']['checked'])) { + print ''; + print ''; +} +print ''; +print ''; +//print ''; +print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); + +print "\n"; + +$colspan = 2 + (empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT) ? 0 : 2); + +if ($conf->use_javascript_ajax) { + print ''; + print ''; + if (!empty($arrayfields['timeconsumed']['checked'])) { + print ''; + print ''; + } + print ''; + + print ''; + +// print ''; +// print ''; + print ''; +} + + +if (count($tasksarray) > 0) { + //var_dump($tasksarray); // contains only selected tasks + //var_dump($tasksarraywithoutfilter); // contains all tasks (if there is a filter, not defined if no filter) + //var_dump($tasksrole); + + $j = 0; + $level = 0; + $totalforvisibletasks = dolisirhLinesPerDay($j, 0, $usertoprocess, $tasksarray, $level, $projectsrole, $tasksrole, $mine, $restrictviewformytask, $daytoparse, $isavailable, 0, $arrayfields, $extrafields); + //var_dump($totalforvisibletasks); + + // Show total for all other tasks + + // Calculate total for all tasks + $listofdistinctprojectid = array(); // List of all distinct projects + if (is_array($tasksarraywithoutfilter) && count($tasksarraywithoutfilter)) { + foreach ($tasksarraywithoutfilter as $tmptask) { + $listofdistinctprojectid[$tmptask->fk_project] = $tmptask->fk_project; + } + } + //var_dump($listofdistinctprojectid); + $totalforeachday = array(); + foreach ($listofdistinctprojectid as $tmpprojectid) { + $projectstatic->id = $tmpprojectid; + $projectstatic->loadTimeSpent($daytoparse, 0, $usertoprocess->id); // Load time spent from table projet_task_time for the project into this->weekWorkLoad and this->weekWorkLoadPerTask for all days of a week + for ($idw = 0; $idw < 7; $idw++) { + $tmpday = dol_time_plus_duree($daytoparse, $idw, 'd'); + $totalforeachday[$tmpday] += $projectstatic->weekWorkLoad[$tmpday]; + } + } + //var_dump($totalforeachday); + + // Is there a diff between selected/filtered tasks and all tasks ? + $isdiff = 0; + if (count($totalforeachday)) { + $timeonothertasks = ($totalforeachday[$daytoparse] - $totalforvisibletasks[$daytoparse]); + if ($timeonothertasks) { + $isdiff = 1; + } + } + + // There is a diff between total shown on screen and total spent by user, so we add a line with all other cumulated time of user + if ($isdiff) { + print ''; + print ''; + if (!empty($arrayfields['timeconsumed']['checked'])) { + print ''; + print ''; + } + print ''; + print ''; + print ' '; + print ' '; + print ''; + } + + if ($conf->use_javascript_ajax) { + print ''; + print ''; + if (!empty($arrayfields['timeconsumed']['checked'])) { + print ''; + print ''; + } + print ''; + + print ''; + +// print ''; + print ''; + } +} else { + print ''; +} +print "
'; +$searchpicto = $form->showFilterAndCheckAddButtons(0); +print $searchpicto; +print '
'.$langs->trans("Project").''.$langs->trans("ThirdParty").''.$langs->trans("Task").''.$langs->trans("PlannedWorkload").'trans("ProgressDeclared")).'">'.$langs->trans("ProgressDeclared").''.$langs->trans("TimeSpent").'
'; + print ''; + print 'Photo'; + print ''.$langs->trans("Everybody").''; + print ''; + print '
'.$langs->trans("TimeSpent").($usertoprocess->firstname ? '
'.$usertoprocess->getNomUrl(-2).''.dol_trunc($usertoprocess->firstname, 10).'' : '').'
'.$langs->trans("HourStart").''; + +// By default, we can edit only tasks we are assigned to +$restrictviewformytask = ((!isset($conf->global->PROJECT_TIME_SHOW_TASK_NOT_ASSIGNED)) ? 2 : $conf->global->PROJECT_TIME_SHOW_TASK_NOT_ASSIGNED); + +$numendworkingday = 0; +$numstartworkingday = 0; +// Get if user is available or not for each day +$isavailable = array(); + +// Assume from Monday to Friday if conf empty or badly formed +$numstartworkingday = 1; +$numendworkingday = 5; + +if (!empty($conf->global->MAIN_DEFAULT_WORKING_DAYS)) { + $tmparray = explode('-', $conf->global->MAIN_DEFAULT_WORKING_DAYS); + if (count($tmparray) >= 2) { + $numstartworkingday = $tmparray[0]; + $numendworkingday = $tmparray[1]; + } +} + +$statusofholidaytocheck = Holiday::STATUS_APPROVED; +$isavailablefordayanduser = $holiday->verifDateHolidayForTimestamp($usertoprocess->id, $daytoparse, $statusofholidaytocheck); // $daytoparse is a date with hours = 0 +$isavailable[$daytoparse] = $isavailablefordayanduser; // in projectLinesPerWeek later, we are using $firstdaytoshow and dol_time_plus_duree to loop on each day + +$test = num_public_holiday($daytoparsegmt, $daytoparsegmt + 86400, $mysoc->country_code); +if ($test) { + $isavailable[$daytoparse] = array('morning'=>false, 'afternoon'=>false, 'morning_reason'=>'public_holiday', 'afternoon_reason'=>'public_holiday'); +} + +$tmparray = dol_getdate($daytoparse, true); // detail of current day +// For monday, must be 0 for monday if MAIN_START_WEEK = 1, must be 1 for monday if MAIN_START_WEEK = 0 +$idw = ($tmparray['wday'] - (empty($conf->global->MAIN_START_WEEK) ? 0 : 1)); +// numstartworkingday and numendworkingday are default start and end date of working days (1 means sunday if MAIN_START_WEEK is 0, 1 means monday if MAIN_START_WEEK is 1) +$cssweekend = ''; +if ((($idw + 1) < $numstartworkingday) || (($idw + 1) > $numendworkingday)) { // This is a day is not inside the setup of working days, so we use a week-end css. + $cssweekend = 'weekend'; +} + +$tmpday = dol_time_plus_duree($daytoparse, $idw, 'd'); + +$cssonholiday = ''; +if (!$isavailable[$daytoparse]['morning'] && !$isavailable[$daytoparse]['afternoon']) { + $cssonholiday .= 'onholidayallday '; +} elseif (!$isavailable[$daytoparse]['morning']) { + $cssonholiday .= 'onholidaymorning '; +} elseif (!$isavailable[$daytoparse]['afternoon']) { + $cssonholiday .= 'onholidayafternoon '; +} + +print ''.$langs->trans("Duration"); +print '
' . $langs->trans('DayWorkTime') . ' : ' . $worked_hours . ':' . $worked_minutes; +print '
' . $langs->trans('ConsumedTime') . ' : ' . $consumed_hours . ':' . $consumed_minutes ; +print '
' . $langs->trans('NonConsumedTime') . ' : ' . $non_consumed_hours . ':' . $non_consumed_minutes; +print ''; +print ''; +print '
'.$langs->trans("Note").'
'; + print $langs->trans("Total"); + print ''; + //print ' - '.$langs->trans("ExpectedWorkedHours").': '.price($usertoprocess->weeklyhours, 1, $langs, 0, 0).''; + print '
 
'; + print $langs->trans("OtherFilteredTasks"); + print ''; + $timeonothertasks = ($totalforeachday[$daytoparse] - $totalforvisibletasks[$daytoparse]); + //if ($timeonothertasks) + //{ + print ''; + //} + print '
'; + print $langs->trans("Total"); + print ''; + //print ' - '.$langs->trans("ExpectedWorkedHours").': '.price($usertoprocess->weeklyhours, 1, $langs, 0, 0).''; + print '
 
'.$langs->trans("NoAssignedTasks").'
"; +print '
'; + +print ''."\n"; + +print '
'; +print ''; +print '
'; + +print '
'; + +$modeinput = 'hours'; + +if ($conf->use_javascript_ajax) { + print "\n\n"; + print ''; +} + +// End of page +llxFooter(); +$db->close(); diff --git a/view/timespent_list.php b/view/timespent_list.php new file mode 100644 index 0000000..2564a28 --- /dev/null +++ b/view/timespent_list.php @@ -0,0 +1,628 @@ + + * Copyright (C) 2022 Florian HENRY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file view/timespent_list.php + * \ingroup dolisirh + * \brief List page for timespent + */ + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) { + $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"] . "/main.inc.php"; +} +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; +$tmp2 = realpath(__FILE__); +$i = strlen($tmp) - 1; +$j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { + $i--; + $j--; +} +if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1)) . "/main.inc.php")) { + $res = @include substr($tmp, 0, ($i + 1)) . "/main.inc.php"; +} +if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1))) . "/main.inc.php")) { + $res = @include dirname(substr($tmp, 0, ($i + 1))) . "/main.inc.php"; +} +// Try main.inc.php using relative path +if (!$res && file_exists("../main.inc.php")) { + $res = @include "../main.inc.php"; +} +if (!$res && file_exists("../../main.inc.php")) { + $res = @include "../../main.inc.php"; +} +if (!$res && file_exists("../../../main.inc.php")) { + $res = @include "../../../main.inc.php"; +} +if (!$res && file_exists("../../../../main.inc.php")) { + $res = @include "../../../../main.inc.php"; +} +if (!$res) { + die("Include of main fails"); +} + +// Global variables definitions +global $conf, $db, $hookmanager, $langs, $user; + +require_once DOL_DOCUMENT_ROOT . '/core/class/html.formcompany.class.php'; +require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php'; +require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php'; +require_once DOL_DOCUMENT_ROOT . '/projet/class/task.class.php'; +if (!empty($conf->categorie->enabled)) { + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcategory.class.php'; + require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; +} + +// Load translation files required by the page +$langs->loadLangs(array("projects", "other", "salaries")); + +// Get parameters +$action = GETPOST('action', 'aZ09') ? GETPOST('action', 'aZ09') : 'view'; // The action 'add', 'create', 'edit', 'update', 'view', ... +$massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists) +$show_files = GETPOST('show_files', 'int'); // Show files area generated by bulk actions ? +$confirm = GETPOST('confirm', 'alpha'); // Result of a confirmation +$cancel = GETPOST('cancel', 'alpha'); // We click on a Cancel button +$toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected into a list +$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'booklist'; // To manage different context of search +$backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page +$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print') + +if (!empty($conf->categorie->enabled)) { + $search_category_array = GETPOST("search_category_".Categorie::TYPE_PROJECT."_list", "array"); +} + +$id = GETPOST('id', 'int'); + +// Load variable for pagination +$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit; +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); +$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int'); +if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) { + // If $page is not defined, or '' or -1 or if we click on clear filters + $page = 0; +} +$offset = $limit * $page; +$pageprev = $page - 1; +$pagenext = $page + 1; + +$hookmanager->initHooks(array('timespentlist')); // Note that conf->hooks_modules contains array + +$arrayfields = array( + 'rowid' => array('tablealias' => 's.', 'fieldalias' => 'socid', 'type' => 'Societe:societe/class/societe.class.php:1:status=1 AND entity IN (__SHARED_ENTITIES__)', 'label' => "Customer", 'checked' => 1, 'position' => 10, 'visible' => 1), + 'ref' => array('tablealias' => 'p.', 'fieldalias' => 'projectref', 'type' => 'Project:projet/class/project.class.php:1', 'label' => "Project", 'checked' => 1, 'position' => 20, 'visible' => 1), + 'p.rowid' => array('fieldalias' => 'projectid', 'type'=> 'text', 'label' => "ProjectId", 'visible' => 0), + 'pt.rowid' => array('fieldalias' => 'taskid', 'type' => 'Task:projet/class/task.class.php:1', 'label' => "Task", 'checked' => 1, 'position' => 30, 'visible' => 1), + 'label' => array('tablealias' => 'pt.', 'type' => 'text', 'label' => "Label", 'checked' => 1, 'position' => 40, 'visible' => 1), + 'task_date' => array('tablealias' => 'ptt.', 'type' => 'datetime', 'label' => "Date", 'checked' => 1, 'position' => 50, 'visible' => 1), + 'fk_user' => array('tablealias' => 'ptt.', 'fieldalias' => 'fk_user', 'type' => 'User:user/class/user.class.php', 'label' => "User", 'checked' => 1, 'position' => 60, 'visible' => 1), + 'task_duration' => array('tablealias' => 'ptt.', 'type' => 'duration', 'label' => "Duration", 'checked' => 1, 'position' => 70, 'visible' => 1, 'isameasure'=>1), + 'note' => array('tablealias' => 'ptt.', 'type' => 'text', 'label' => "Note", 'checked' => 1, 'position' => 80, 'visible' => 1), + 'thm' => array('tablealias' => 'ptt.', 'type' => 'price', 'label' => "Value", 'checked' => 1, 'position' => 90, 'visible' => 1, 'isameasure'=>1), + 'invoice_id' => array('tablealias' => 'ptt.', 'fieldalias' => 'invoice_id', 'type' => 'Facture:compta/facture/class/facture.class.php:1', 'label' => "Facture", 'checked' => 1, 'position' => 100, 'visible' => 1), + 'ts.rowid' => array('fieldalias' => 'timesheetid', 'type' => 'TimeSheet:custom/dolisirh/class/timesheet.class.php:1', 'label' => "TimeSheet", 'checked' => 1, 'position' => 110, 'visible' => 1), +); + +// Default sort order (if not yet defined by previous GETPOST) +if (!$sortfield) { + $sortfield = 'ptt.task_date'; // Set here default search field. By default 1st field in definition. +} +if (!$sortorder) { + $sortorder = "ASC"; +} + +$arrayfields = dol_sort_array($arrayfields, 'position'); + +// Initialize array of search criterias +$search_all = GETPOST('search_all', 'alphanohtml'); +$search = array(); +foreach ($arrayfields as $key => $val) { + $keysearch = (array_key_exists('fieldalias', $val) ? $val['fieldalias'] : $key); + if (GETPOST('search_' . $keysearch, 'alpha') !== '' && GETPOST('search_' . $keysearch, 'alpha') !== '-1') { + $search[$keysearch] = GETPOST('search_' . $keysearch, 'alpha'); + } + if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) { + $search[$keysearch . '_dtstart'] = dol_mktime(0, 0, 0, GETPOST('search_' . $keysearch . '_dtstartmonth', 'int'), GETPOST('search_' . $keysearch . '_dtstartday', 'int'), GETPOST('search_' . $keysearch . '_dtstartyear', 'int')); + $search[$keysearch . '_dtend'] = dol_mktime(23, 59, 59, GETPOST('search_' . $keysearch . '_dtendmonth', 'int'), GETPOST('search_' . $keysearch . '_dtendday', 'int'), GETPOST('search_' . $keysearch . '_dtendyear', 'int')); + } +} + +$permissiontoread = $user->rights->projet->lire; +$permissiontoadd = $user->rights->projet->creer; +$permissiontodelete = $user->rights->projet->supprimer; + + +// Security check (enable the most restrictive one) +if ($user->socid > 0) accessforbidden(); +if (empty($conf->dolisirh->enabled)) accessforbidden('Module not enabled'); + +/* + * Actions + */ + +if (GETPOST('cancel', 'alpha')) { + $action = 'list'; + $massaction = ''; +} +if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { + $massaction = ''; +} + +$parameters = array(); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} + +if (empty($reshook)) { + // Selection of new fields + include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php'; + + // Purge search criteria + if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers + foreach ($arrayfields as $key => $val) { + $keysearch = (array_key_exists('fieldalias', $val) ? $val['fieldalias'] : $key); + $search[$keysearch] = ''; + if (preg_match('/^(date|timestamp|datetime)/', $val['type'])) { + $search[$keysearch . '_dtstart'] = ''; + $search[$keysearch . '_dtend'] = ''; + } + } + $toselect = array(); + $search_array_options = array(); + $search_category_array = array(); + } + if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha') + || GETPOST('button_search_x', 'alpha') || GETPOST('button_search.x', 'alpha') || GETPOST('button_search', 'alpha')) { + $massaction = ''; // Protection to avoid mass action if we force a new search during a mass action confirmation + } + + // Mass actions + $objectclass = 'Task'; + $objectlabel = 'Task'; + $uploaddir = $conf->dolisirh->dir_output; + include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php'; +} + + +/* + * View + */ + +$form = new Form($db); + +$now = dol_now(); + +$help_url = ''; +$title = $langs->trans($langs->transnoentitiesnoconv("TimeSpentList")); +$morejs = array(); +$morecss = array(); + + +// Build and execute select +// -------------------------------------------------------------------- +$sql = 'SELECT '; +$sql .= 'DISTINCT '; +$sqlfields = array(); +foreach ($arrayfields as $field => $data) { + $sqlfields[] = $data['tablealias'] . $field . ((array_key_exists('fieldalias', $data) ? ' as ' . $data['fieldalias'] : '')); +} +$sql .= implode(',', $sqlfields); + +// Add fields from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= preg_replace('/^,/', '', $hookmanager->resPrint); +$sql = preg_replace('/,\s*$/', '', $sql); +$sql .= ' FROM ' . MAIN_DB_PREFIX . 'projet as p'; +$sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'projet_extrafields as extra ON p.rowid = extra.fk_object'; +$sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'c_lead_status as cls ON p.fk_opp_status = cls.rowid'; +$sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'projet_task as pt ON p.rowid = pt.fk_projet'; +$sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'projet_task_extrafields as ef ON pt.rowid = ef.fk_object'; +$sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'projet_task_time as ptt ON pt.rowid = ptt.fk_task'; +$sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'societe as s ON p.fk_soc = s.rowid'; +$sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'facture as f ON ptt.invoice_id = f.rowid'; +$sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'element_element as ee on ( ee.sourcetype = "dolisirh_timesheet" AND ee.targettype = "project_task_time" AND ee.fk_target = ptt.rowid)'; +$sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'dolisirh_timesheet as ts ON ee.fk_source = ts.rowid'; + +// Add table from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; +if ($object->ismultientitymanaged == 1) { + $sql .= " WHERE p.entity IN (" . getEntity($object->element) . ")"; +} else { + $sql .= " WHERE 1 = 1"; +} +$sql .= ' AND ptt.task_duration IS NOT NULL'; + +foreach ($search as $key => $val) { + if (preg_match('/(_dtstart|_dtend)$/', $key) && $search[$key] != '') { + if (preg_match('/_dtstart$/', $key)) { + $sql .= " AND ptt.task_date >= '" . $db->idate($search[$key]) . "'"; + } + if (preg_match('/_dtend$/', $key)) { + $sql .= " AND ptt.task_date <= '" . $db->idate($search[$key]) . "'"; + } + } + if ($key == 'socid' && !empty($val)) $sql .= ' AND s.rowid=' . (int)$val; + if ($key == 'projectref' && !empty($val)) $sql .= ' AND p.rowid=' . (int)$val; + if ($key == 'taskid' && !empty($val)) $sql .= ' AND pt.rowid=' . (int)$val; + if ($key == 'fk_user' && !empty($val)) $sql .= ' AND ptt.fk_user=' . (int)$val; + if ($key == 'invoice_id' && !empty($val)) $sql .= ' AND ptt.invoice_id=' . (int)$val; + if ($key == 'timesheetid' && !empty($val)) $sql .= ' AND ts.rowid=' . (int)$val; +} + +if (!empty($conf->categorie->enabled)) { + $sql .= Categorie::getFilterSelectQuery(Categorie::TYPE_PROJECT, "p.rowid", $search_category_array); +} + +if ($search_all) { + $sql .= natural_search(array_keys($fieldstosearchall), $search_all); +} +// Add where from extra fields +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; +// Add where from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql .= $hookmanager->resPrint; + +// Count total nb of records +$nbtotalofrecords = ''; +if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { + $sqlforcount = preg_replace('/^SELECT[a-z0-9\._\s\(\),]+FROM/i', 'SELECT COUNT(*) as nbtotalofrecords FROM', $sql); + $resql = $db->query($sqlforcount); + $objforcount = $db->fetch_object($resql); + $nbtotalofrecords = $objforcount->nbtotalofrecords; + if (($page * $limit) > $nbtotalofrecords) { // if total of record found is smaller than page * limit, goto and load page 0 + $page = 0; + $offset = 0; + } + $db->free($resql); +} + +// Complete request and execute it with limit +$sql .= $db->order($sortfield, $sortorder); +if ($limit) { + $sql .= $db->plimit($limit + 1, $offset); +} + +$resql = $db->query($sql); +if (!$resql) { + dol_print_error($db); + exit; +} + +$num = $db->num_rows($resql); + +// Output page +// -------------------------------------------------------------------- + +llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', ''); + +$arrayofselected = is_array($toselect) ? $toselect : array(); + +$param = ''; +if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { + $param .= '&contextpage=' . urlencode($contextpage); +} +if ($limit > 0 && $limit != $conf->liste_limit) { + $param .= '&limit=' . urlencode($limit); +} +foreach ($search as $key => $val) { + if (is_array($search[$key]) && count($search[$key])) { + foreach ($search[$key] as $skey) { + if ($skey != '') { + $param .= '&search_' . $key . '[]=' . urlencode($skey); + } + } + } elseif ($search[$key] != '') { + $param .= '&search_' . $key . '=' . urlencode($search[$key]); + } +} +if ($optioncss != '') { + $param .= '&optioncss=' . urlencode($optioncss); +} +// Add $param from extra fields +include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_list_search_param.tpl.php'; +// Add $param from hooks +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object); // Note that $action and $object may have been modified by hook +$param .= $hookmanager->resPrint; + +// List of mass actions available +$arrayofmassactions = array(); +if ($permissiontodelete) { + $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete"); +} +if (GETPOST('nomassaction', 'int') || in_array($massaction, array('predelete'))) { + $arrayofmassactions = array(); +} +//$massactionbutton = $form->selectMassAction('', $arrayofmassactions); + +print '
' . "\n"; +if ($optioncss != '') { + print ''; +} +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'clock', 0, 0, '', $limit, 0, 0, 1); + +include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; + +if ($search_all) { + $setupstring = ''; + foreach ($fieldstosearchall as $key => $val) { + $fieldstosearchall[$key] = $langs->trans($val); + $setupstring .= $key."=".$val.";"; + } + print ''."\n"; + print '
'.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'
'."\n"; +} + +$moreforfilter = ''; +$parameters = array(); +$reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook +if (empty($reshook)) { + $moreforfilter .= $hookmanager->resPrint; +} else { + $moreforfilter = $hookmanager->resPrint; +} + +// Filter on categories +if (!empty($conf->categorie->enabled) && $user->rights->categorie->lire) { + $formcategory = new FormCategory($db); + $moreforfilter .= $formcategory->getFilterBox(Categorie::TYPE_PROJECT, $search_category_array); +} + +if (!empty($moreforfilter)) { + print '
'; + print $moreforfilter; + print '
'; +} + +$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; +$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields +$selectedfields .= (is_array($arrayofmassactions) && count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : ''); + +print '
'; // You can use div-table-responsive-no-min if you dont need reserved height for your table +print '' . "\n"; + + +// -------------------------------------------------------------------- +print ''; +foreach ($arrayfields as $key => $val) { + $keysearch = (array_key_exists('fieldalias', $val) ? $val['fieldalias'] : $key); + $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); + if ($key == 'status') { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } elseif (in_array($val['type'], array('timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { + $cssforfield .= ($cssforfield ? ' ' : '').'right'; + } + if (!empty($arrayfields[$key]['checked'])) { + print ''; + } +} +// Extra fields +include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_list_search_input.tpl.php'; + +// Fields from hook +$parameters = array('arrayfields' => $arrayfields); +$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; +// Action column +print ''; +print '' . "\n"; + +// Fields title label +// -------------------------------------------------------------------- +print ''; +foreach ($arrayfields as $key => $val) { + $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); + if ($key == 'status') { + $cssforfield .= ($cssforfield ? ' ' : '') . 'center'; + } elseif (in_array($val['type'], array('date', 'datetime', 'timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '') . 'center'; + } elseif (in_array($val['type'], array('timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '') . 'nowrap'; + } elseif (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', + 'price')) && $val['label'] != 'TechnicalID' && empty($val['arrayofkeyval'])) { + $cssforfield .= ($cssforfield ? ' ' : '') . 'right'; + } + if (!empty($arrayfields[$key]['checked'])) { + print getTitleFieldOfList($arrayfields[$key]['label'], 0, $_SERVER['PHP_SELF'], $val['tablealias'] . $key, '', $param, ($cssforfield ? 'class="' . $cssforfield . '"' : ''), $sortfield, $sortorder, ($cssforfield ? $cssforfield . ' ' : '')) . "\n"; + } +} +// Extra fields +include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_list_search_title.tpl.php'; +// Hook fields +$parameters = array('arrayfields' => $arrayfields, 'param' => $param, 'sortfield' => $sortfield, 'sortorder' => $sortorder); +$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; +// Action column +print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ') . "\n"; +print '' . "\n"; + +// Loop on record +// -------------------------------------------------------------------- +$i = 0; +$totalarray = array(); +$totalarray['nbfield'] = 0; +$totalarray['type'][8]='duration'; +while ($i < ($limit ? min($num, $limit) : $num)) { + $obj = $db->fetch_object($resql); + if (empty($obj)) { + break; // Should not happen + } + + // Show here line of result + print ''; + foreach ($arrayfields as $key => $val) { + if ($val['visible'] == 1) { + $cssforfield = (empty($val['csslist']) ? (empty($val['css']) ? '' : $val['css']) : $val['csslist']); + if (in_array($val['type'], array('date', 'datetime', 'timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } elseif ($key == 'status') { + $cssforfield .= ($cssforfield ? ' ' : '').'center'; + } + + if (in_array($val['type'], array('timestamp'))) { + $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + } elseif ($key == 'ref') { + $cssforfield .= ($cssforfield ? ' ' : '').'nowrap'; + } + + if (in_array($val['type'], array('double(24,8)', 'double(6,3)', 'integer', 'real', 'price')) && !in_array($key, array('rowid', 'status')) && empty($val['arrayofkeyval'])) { + $cssforfield .= ($cssforfield ? ' ' : '').'right'; + } + + if (!empty($arrayfields[$key]['checked'])) { + print ''; + if (in_array($val['fieldalias'], array('socid', 'projectref', 'fk_user', 'taskid', 'invoice_id', 'timesheetid'))) { + $InfoFieldList = explode(':', $val['type']); + $classname = $InfoFieldList[0]; + $classpath = $InfoFieldList[1]; + if (!empty($classpath)) { + dol_include_once($InfoFieldList[1]); + if ($classname && class_exists($classname)) { + $object = new $classname($db); + if ($val['fieldalias'] == 'projectref') { + $object->fetch($obj->projectid); + print $object->getNomUrl(1, '', 1); + } else { + $object->fetch($obj->{$val['fieldalias']}); + if (!empty($obj->{$val['fieldalias']})) { + print $object->getNomUrl(1); + } + } + } + } + } elseif ($key == 'task_date') { + print dol_print_date($obj->task_date, 'day'); + } elseif ($key == 'title' || $key === 'label' || $key == 'note') { + print $obj->{$key}; + } elseif ($key == 'task_duration') { + print convertSecondToTime($obj->task_duration, 'allhourmin'); + } elseif ($key == 'thm') { + $value = price2num($obj->thm * $obj->task_duration / 3600, 'MT', 1); + print 'thm).'">'; + print price($value, 1, $langs, 1, -1, -1, $conf->currency); + } + print ''; + if (!$i) { + $totalarray['nbfield']++; + } + if (!empty($val['isameasure']) && $val['isameasure'] == 1) { + if (!$i) { + $totalarray['pos'][$totalarray['nbfield']] = $key; + } + if (!isset($totalarray['val'])) { + $totalarray['val'] = array(); + } + if (!isset($totalarray['val'][$key])) { + $totalarray['val'][$key] = 0; + } + $totalarray['val'][$key] += convertSecondToTime($obj->{$key}, 'allhourmin'); + if ($key == 'thm') { + $totalarray['val'][$key] += $value; + } + } + } + } + } + // Fields from hook + $parameters = array('arrayfields' => $arrayfields, 'object' => $object, 'obj' => $obj, 'i' => $i, 'totalarray' => &$totalarray); + $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object); // Note that $action and $object may have been modified by hook + // Action column + print ''; + print $hookmanager->resPrint; + if (!$i) { + $totalarray['nbfield']++; + } + print ''; + print '' . "\n"; + + $i++; +} + +// Show total line +include DOL_DOCUMENT_ROOT . '/core/tpl/list_print_total.tpl.php'; + +// If no record found +if ($num == 0) { + $colspan = 1; + foreach ($arrayfields as $key => $val) { + if (!empty($val['checked'])) { + $colspan++; + } + } + print ''; +} + +$db->free($resql); + +$parameters = array('arrayfields' => $arrayfields, 'sql' => $sql); +$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; + +print '
'; + if (in_array($val['fieldalias'], array('socid','projectref', 'fk_user','taskid', 'invoice_id', 'timesheetid'))) { + print $form->selectForForms($val['type'], 'search_' . $keysearch, $search[$keysearch], 1, '', '', $morecss); + } elseif (preg_match('/^(date|timestamp|datetime)/', $val['type'])) { + print '
'; + print $form->selectDate($search[$key . '_dtstart'], "search_" . $key . "_dtstart", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From')); + print '
'; + print '
'; + print $form->selectDate($search[$key . '_dtend'], "search_" . $key . "_dtend", 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to')); + print '
'; + } + print '
'; +$searchpicto = $form->showFilterButtons(); +print $searchpicto; +print '
'; + if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + $selected = 0; + if (in_array($object->id, $arrayofselected)) { + $selected = 1; + } + print ''; + } + print '
' . $langs->trans("NoRecordFound") . '
' . "\n"; +print '
' . "\n"; + +print '
' . "\n"; + +// End of page +llxFooter(); +$db->close(); + diff --git a/view/timespent_month.php b/view/timespent_month.php new file mode 100644 index 0000000..3cb5aeb --- /dev/null +++ b/view/timespent_month.php @@ -0,0 +1,1067 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file view/timespent_month.php + * \ingroup doliprojet + * \brief List timespent of tasks per day on each month + */ + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if ( ! $res && ! empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"] . "/main.inc.php"; +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } +if ( ! $res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1)) . "/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1)) . "/main.inc.php"; +if ( ! $res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1))) . "/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1))) . "/main.inc.php"; +// Try main.inc.php using relative path +if ( ! $res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; +if ( ! $res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; +if ( ! $res) die("Include of main fails"); + +// Libraries +require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; +require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; +require_once DOL_DOCUMENT_ROOT.'/holiday/class/holiday.class.php'; +if (!empty($conf->categorie->enabled)) { + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcategory.class.php'; + require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; +} + +require_once DOL_DOCUMENT_ROOT.'/custom/dolisirh/lib/dolisirh_function.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/custom/dolisirh/class/workinghours.class.php'; + +// Global variables definitions +global $conf, $db, $hookmanager, $langs, $user; + +// Load translation files required by the page +$langs->loadLangs(array('projects', 'users', 'companies')); + +// Get parameters +$action = GETPOST('action', 'aZ09'); +$mode = GETPOST("mode", 'alpha'); +$id = GETPOST('id', 'int'); +$taskid = GETPOST('taskid', 'int'); +$contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'permonthcard'; + +$mine = 0; +if ($mode == 'mine') { + $mine = 1; +} + +$projectid = GETPOSTISSET("id") ? GETPOST("id", "int", 1) : GETPOST("projectid", "int"); + +$hookmanager->initHooks(array('timesheetpermonthcard')); + +// Security check +$socid = 0; +// For external user, no check is done on company because readability is managed by public status of project and assignement. +// if ($user->socid > 0) $socid=$user->socid; +$result = restrictedArea($user, 'projet', $projectid); + +$now = dol_now(); +$year = GETPOST('reyear', 'int') ?GETPOST('reyear', 'int') : (GETPOST("year", 'int') ?GETPOST("year", "int") : date("Y")); +$month = GETPOST('remonth', 'int') ?GETPOST('remonth', 'int') : (GETPOST("month", 'int') ?GETPOST("month", "int") : date("m")); +$day = GETPOST('reday', 'int') ?GETPOST('reday', 'int') : (GETPOST("day", 'int') ?GETPOST("day", "int") : date("d")); +$week = GETPOST("week", "int") ?GETPOST("week", "int") : date("W"); + +$day = (int) $day; +$dayInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year); + +//$search_categ = GETPOST("search_categ", 'alpha'); +$search_usertoprocessid = GETPOST('search_usertoprocessid', 'int'); +$search_task_ref = GETPOST('search_task_ref', 'alpha'); +$search_task_label = GETPOST('search_task_label', 'alpha'); +$search_project_ref = GETPOST('search_project_ref', 'alpha'); +$search_thirdparty = GETPOST('search_thirdparty', 'alpha'); +$search_declared_progress = GETPOST('search_declared_progress', 'alpha'); + +if (!empty($conf->categorie->enabled)) { + $search_category_array = GETPOST("search_category_".Categorie::TYPE_PROJECT."_list", "array"); +} + +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); + +// Define firstdaytoshow and lastdaytoshow (warning: lastdaytoshow is last second to show + 1) +$firstdaytoshow = dol_get_first_day($year, $month); +$firstdaytoshowgmt = dol_get_first_day($year, $month, true); + +$currentMonth = date('m', dol_now()); +if ($currentMonth == $month) { + $lastdaytoshow = dol_now(); + $lastday = dol_print_date(dol_now(), 'dayrfc'); +} else { + $lastdaytoshow = dol_get_last_day($year, $month); + $lastday = dol_print_date($lastdaytoshow, 'dayrfc'); +} + +$prev = dol_get_prev_month($month, $year); +$prev_year = $prev['year']; +$prev_month = $prev['month']; + +$next = dol_get_next_month($month, $year); +$next_year = $next['year']; +$next_month = $next['month']; + +if (empty($search_usertoprocessid) || $search_usertoprocessid == $user->id) { + $usertoprocess = $user; + $search_usertoprocessid = $usertoprocess->id; +} elseif ($search_usertoprocessid > 0) { + $usertoprocess = new User($db); + $usertoprocess->fetch($search_usertoprocessid); + $search_usertoprocessid = $usertoprocess->id; +} else { + $usertoprocess = new User($db); +} + +$object = new Task($db); + +// Extra fields +$extrafields = new ExtraFields($db); + +// fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +// Definition of fields for list +$arrayfields = array(); +/*$arrayfields=array( + // Project + 'p.opp_amount'=>array('label'=>$langs->trans("OpportunityAmountShort"), 'checked'=>0, 'enabled'=>($conf->global->PROJECT_USE_OPPORTUNITIES?1:0), 'position'=>103), + 'p.fk_opp_status'=>array('label'=>$langs->trans("OpportunityStatusShort"), 'checked'=>0, 'enabled'=>($conf->global->PROJECT_USE_OPPORTUNITIES?1:0), 'position'=>104), + 'p.opp_percent'=>array('label'=>$langs->trans("OpportunityProbabilityShort"), 'checked'=>0, 'enabled'=>($conf->global->PROJECT_USE_OPPORTUNITIES?1:0), 'position'=>105), + 'p.budget_amount'=>array('label'=>$langs->trans("Budget"), 'checked'=>0, 'position'=>110), + 'p.usage_bill_time'=>array('label'=>$langs->trans("BillTimeShort"), 'checked'=>0, 'position'=>115), + );*/ +$arrayfields['timeconsumed'] = array('label'=>'TimeConsumed', 'checked'=>1, 'enabled'=>1, 'position'=>15); +/*foreach($object->fields as $key => $val) + { + // If $val['visible']==0, then we never show the field + if (! empty($val['visible'])) $arrayfields['t.'.$key]=array('label'=>$val['label'], 'checked'=>(($val['visible']<0)?0:1), 'enabled'=>$val['enabled'], 'position'=>$val['position']); + }*/ +// Definition of fields for list +// Extra fields +if (!empty($extrafields->attributes['projet_task']['label']) && is_array($extrafields->attributes['projet_task']['label']) && count($extrafields->attributes['projet_task']['label']) > 0) { + foreach ($extrafields->attributes['projet_task']['label'] as $key => $val) { + if (!empty($extrafields->attributes['projet_task']['list'][$key])) { + $arrayfields["efpt.".$key] = array('label'=>$extrafields->attributes['projet_task']['label'][$key], 'checked'=>(($extrafields->attributes['projet_task']['list'][$key] < 0) ? 0 : 1), 'position'=>$extrafields->attributes['projet_task']['pos'][$key], 'enabled'=>(abs((int) $extrafields->attributes['projet_task']['list'][$key]) != 3 && $extrafields->attributes['projet_task']['perms'][$key])); + } + } +} +$arrayfields = dol_sort_array($arrayfields, 'position'); + +$search_array_options = array(); +$search_array_options_project = $extrafields->getOptionalsFromPost('projet', '', 'search_'); +$search_array_options_task = $extrafields->getOptionalsFromPost('projet_task', '', 'search_task_'); + +/* + * Actions + */ + +$parameters = array('id' => $id, 'taskid' => $taskid, 'projectid' => $projectid); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} +// Purge criteria +if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers + $action = ''; + //$search_categ = ''; + $search_usertoprocessid = $user->id; + $search_task_ref = ''; + $search_task_label = ''; + $search_project_ref = ''; + $search_thirdparty = ''; + $search_declared_progress = ''; + + $search_array_options_project = array(); + $search_array_options_task = array(); + $search_category_array = array(); + + // We redefine $usertoprocess + $usertoprocess = $user; +} +if (GETPOST("button_search_x", 'alpha') || GETPOST("button_search.x", 'alpha') || GETPOST("button_search", 'alpha')) { + $action = ''; +} + +if (GETPOST('submitdateselect')) { + if (GETPOST('remonth', 'int') && GETPOST('reday', 'int') && GETPOST('reyear', 'int')) { + $daytoparse = dol_mktime(0, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int')); + } + + $action = ''; +} + +include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php'; + +if ($action == 'addtime' && $user->rights->projet->lire && GETPOST('assigntask') && GETPOST('formfilteraction') != 'listafterchangingselectedfields') { + $action = 'assigntask'; + + if ($taskid > 0) { + $result = $object->fetch($taskid, $ref); + if ($result < 0) { + $error++; + } + } else { + setEventMessages($langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Task")), '', 'errors'); + $error++; + } + if (!GETPOST('type')) { + setEventMessages($langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), '', 'errors'); + $error++; + } + + if (!$error) { + $idfortaskuser = $usertoprocess->id; + $result = $object->add_contact($idfortaskuser, GETPOST("type"), 'internal'); + + if ($result >= 0 || $result == -2) { // Contact add ok or already contact of task + // Test if we are already contact of the project (should be rare but sometimes we can add as task contact without being contact of project, like when admin user has been removed from contact of project) + $sql = 'SELECT ec.rowid FROM '.MAIN_DB_PREFIX.'element_contact as ec, '.MAIN_DB_PREFIX.'c_type_contact as tc WHERE tc.rowid = ec.fk_c_type_contact'; + $sql .= ' AND ec.fk_socpeople = '.((int) $idfortaskuser)." AND ec.element_id = ".((int) $object->fk_project)." AND tc.element = 'project' AND source = 'internal'"; + $resql = $db->query($sql); + if ($resql) { + $obj = $db->fetch_object($resql); + if (!$obj) { // User is not already linked to project, so we will create link to first type + $project = new Project($db); + $project->fetch($object->fk_project); + // Get type + $listofprojcontact = $project->liste_type_contact('internal'); + + if (count($listofprojcontact)) { + $typeforprojectcontact = reset(array_keys($listofprojcontact)); + $result = $project->add_contact($idfortaskuser, $typeforprojectcontact, 'internal'); + } + } + } else { + dol_print_error($db); + } + } + } + + if ($result < 0) { + $error++; + if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') { + $langs->load("errors"); + setEventMessages($langs->trans("ErrorTaskAlreadyAssigned"), null, 'warnings'); + } else { + setEventMessages($object->error, $object->errors, 'errors'); + } + } + + if (!$error) { + setEventMessages("TaskAssignedToEnterTime", null); + $taskid = 0; + } + + $action = ''; +} + +if ($action == 'addtime' && $user->rights->projet->lire && GETPOST('formfilteraction') != 'listafterchangingselectedfields') { + $timetoadd = $_POST['task']; + if (empty($timetoadd)) { + setEventMessages($langs->trans("ErrorTimeSpentIsEmpty"), null, 'errors'); + } else { + foreach ($timetoadd as $taskid => $value) { // Loop on each task + $updateoftaskdone = 0; + foreach ($value as $key => $val) { // Loop on each day + $amountoadd = $timetoadd[$taskid][$key]; + if (!empty($amountoadd)) { + $tmpduration = explode(':', $amountoadd); + $newduration = 0; + if (!empty($tmpduration[0])) { + $newduration += ($tmpduration[0] * 3600); + } + if (!empty($tmpduration[1])) { + $newduration += ($tmpduration[1] * 60); + } + if (!empty($tmpduration[2])) { + $newduration += ($tmpduration[2]); + } + + if ($newduration > 0) { + $object->fetch($taskid); + + if (GETPOSTISSET($taskid.'progress')) { + $object->progress = GETPOST($taskid.'progress', 'int'); + } else { + unset($object->progress); + } + + $object->timespent_duration = $newduration; + $object->timespent_fk_user = $usertoprocess->id; + $object->timespent_date = dol_time_plus_duree($firstdaytoshow, $key, 'd'); + $object->timespent_datehour = $object->timespent_date; + $object->timespent_note = $object->description; + + $result = $object->addTimeSpent($user); + if ($result < 0) { + setEventMessages($object->error, $object->errors, 'errors'); + $error++; + break; + } + + $updateoftaskdone++; + } + } + } + + if (!$updateoftaskdone) { // Check to update progress if no update were done on task. + $object->fetch($taskid); + //var_dump($object->progress);var_dump(GETPOST($taskid . 'progress', 'int')); exit; + if ($object->progress != GETPOST($taskid.'progress', 'int')) { + $object->progress = GETPOST($taskid.'progress', 'int'); + $result = $object->update($user); + if ($result < 0) { + setEventMessages($object->error, $object->errors, 'errors'); + $error++; + break; + } + } + } + } + + if (!$error) { + setEventMessages($langs->trans("RecordSaved"), null, 'mesgs'); + + $param = ''; + $param .= ($mode ? '&mode='.urlencode($mode) : ''); + $param .= ($projectid ? 'id='.urlencode($projectid) : ''); + $param .= ($search_usertoprocessid ? '&search_usertoprocessid='.urlencode($search_usertoprocessid) : ''); + $param .= ($day ? '&day='.urlencode($day) : '').($month ? '&month='.urlencode($month) : '').($year ? '&year='.urlencode($year) : ''); + $param .= ($search_project_ref ? '&search_project_ref='.urlencode($search_project_ref) : ''); + $param .= ($search_usertoprocessid > 0 ? '&search_usertoprocessid='.urlencode($search_usertoprocessid) : ''); + $param .= ($search_thirdparty ? '&search_thirdparty='.urlencode($search_thirdparty) : ''); + $param .= ($search_declared_progress ? '&search_declared_progress='.urlencode($search_declared_progress) : ''); + $param .= ($search_task_ref ? '&search_task_ref='.urlencode($search_task_ref) : ''); + $param .= ($search_task_label ? '&search_task_label='.urlencode($search_task_label) : ''); + + /*$search_array_options=$search_array_options_project; + $search_options_pattern='search_options_'; + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; + */ + + $search_array_options = $search_array_options_task; + $search_options_pattern = 'search_task_options_'; + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; + + // Redirect to avoid submit twice on back + header('Location: '.$_SERVER["PHP_SELF"].'?'.$param); + exit; + } + } +} + +if ($action == 'showOnlyFavoriteTasks') { + if ($conf->global->DOLISIRH_SHOW_ONLY_FAVORITE_TASKS == 1) { + dolibarr_set_const($db, 'DOLISIRH_SHOW_ONLY_FAVORITE_TASKS', 0, 'integer', 0, '', $conf->entity); + } else { + dolibarr_set_const($db, 'DOLISIRH_SHOW_ONLY_FAVORITE_TASKS', 1, 'integer', 0, '', $conf->entity); + } +} + + +/* + * View + */ + +$form = new Form($db); +$formother = new FormOther($db); +$formcompany = new FormCompany($db); +$formproject = new FormProjets($db); +$projectstatic = new Project($db); +$project = new Project($db); +$taskstatic = new Task($db); +$thirdpartystatic = new Societe($db); +$holiday = new Holiday($db); + +$title = $langs->trans("TimeSpent"); +$help_url = ''; +$morejs = array("/dolisirh/js/dolisirh.js.php", "/core/js/timesheet.js"); +$morecss = array("/dolisirh/css/dolisirh.css"); + +$projectsListId = $projectstatic->getProjectsAuthorizedForUser($usertoprocess, (empty($usertoprocess->id) ? 2 : 0), 1); // Return all project i have permission on (assigned to me+public). I want my tasks and some of my task may be on a public projet that is not my project +//var_dump($projectsListId); +if ($id) { + $project->fetch($id); + $project->fetch_thirdparty(); +} + +$onlyopenedproject = 1; // or -1 +$morewherefilter = ''; + +if ($search_project_ref) { + $morewherefilter .= natural_search(array("p.ref", "p.title"), $search_project_ref); +} +if ($search_task_ref) { + $morewherefilter .= natural_search("t.ref", $search_task_ref); +} +if ($search_task_label) { + $morewherefilter .= natural_search(array("t.ref", "t.label"), $search_task_label); +} +if ($search_thirdparty) { + $morewherefilter .= natural_search("s.nom", $search_thirdparty); +} +if ($search_declared_progress) { + $morewherefilter .= natural_search("t.progress", $search_declared_progress, 1); +} +if (!empty($conf->categorie->enabled)) { + $morewherefilter .= Categorie::getFilterSelectQuery(Categorie::TYPE_PROJECT, "p.rowid", $search_category_array); +} + +$sql = &$morewherefilter; + +/*$search_array_options = $search_array_options_project; + $extrafieldsobjectprefix='efp.'; + $search_options_pattern='search_options_'; + $extrafieldsobjectkey='projet'; + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; + */ +$search_array_options = $search_array_options_task; +$extrafieldsobjectprefix = 'efpt.'; +$search_options_pattern = 'search_task_options_'; +$extrafieldsobjectkey = 'projet_task'; +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; + +$tasksarray = $taskstatic->getTasksArray(0, 0, ($project->id ? $project->id : 0), $socid, 0, $search_project_ref, $onlyopenedproject, $morewherefilter, ($search_usertoprocessid ? $search_usertoprocessid : 0), 0, $extrafields); +//$tasksarray = getFavoriteTasksArray($taskstatic->id, 0, 0, ($project->id ? $project->id : 0), $socid, 0, $search_project_ref, $onlyopenedproject, $morewherefilter, ($search_usertoprocessid ? $search_usertoprocessid : 0), 0, $extrafields); // We want to see all tasks of open project i am allowed to see and that match filter, not only my tasks. Later only mine will be editable later. +if (!empty($conf->global->DOLISIRH_SHOW_ONLY_FAVORITE_TASKS)) { // Get all task without any filter, so we can show total of time spent for not visible tasks + $tasksarraywithoutfilter = $taskstatic->getTasksArray(0, 0, ($project->id ? $project->id : 0), $socid, 0, $search_project_ref, $onlyopenedproject, $morewherefilter, ($search_usertoprocessid ? $search_usertoprocessid : 0)); // We want to see all tasks of open project i am allowed to see and that match filter, not only my tasks. Later only mine will be editable later. +} +$projectsrole = $taskstatic->getUserRolesForProjectsOrTasks($usertoprocess, 0, ($project->id ? $project->id : 0), 0, $onlyopenedproject); +$tasksrole = $taskstatic->getUserRolesForProjectsOrTasks(0, $usertoprocess, ($project->id ? $project->id : 0), 0, $onlyopenedproject); + +llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss); + +//print_barre_liste($title, $page, $_SERVER["PHP_SELF"], "", $sortfield, $sortorder, "", $num, '', 'project'); + +$param = ''; +$param .= ($mode ? '&mode='.urlencode($mode) : ''); +$param .= ($search_project_ref ? '&search_project_ref='.urlencode($search_project_ref) : ''); +$param .= ($search_usertoprocessid > 0 ? '&search_usertoprocessid='.urlencode($search_usertoprocessid) : ''); +$param .= ($search_thirdparty ? '&search_thirdparty='.urlencode($search_thirdparty) : ''); +$param .= ($search_task_ref ? '&search_task_ref='.urlencode($search_task_ref) : ''); +$param .= ($search_task_label ? '&search_task_label='.urlencode($search_task_label) : ''); + +$search_array_options = $search_array_options_project; +$search_options_pattern = 'search_options_'; +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; + +$search_array_options = $search_array_options_task; +$search_options_pattern = 'search_task_options_'; +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; + +// Show navigation bar +$nav = ''.img_previous($langs->trans("Previous")).''; +$nav .= ''.dol_print_date(dol_mktime(0, 0, 0, $month, $day, $year), "%B %Y").''; +$nav .= ''.img_next($langs->trans("Next")).''; +$nav .= $form->selectDate(-1, '', 0, 0, 2, "addtime", 1, 1); +$nav .= ''; + +$picto = 'clock'; + +print '
'; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +$head = dolisirh_timesheet_prepare_head($mode, $usertoprocess); +print dol_get_fiche_head($head, 'inputpermonth', $langs->trans('TimeSpent'), -1, $picto); + +// Show description of content +print '
'; +if ($mine || ($usertoprocess->id == $user->id)) { + print $langs->trans("MyTasksDesc").'.'.($onlyopenedproject ? ' '.$langs->trans("OnlyOpenedProject") : '').'
'; +} else { + if (empty($usertoprocess->id) || $usertoprocess->id < 0) { + if ($user->rights->projet->all->lire && !$socid) { + print $langs->trans("ProjectsDesc").'.'.($onlyopenedproject ? ' '.$langs->trans("OnlyOpenedProject") : '').'
'; + } else { + print $langs->trans("ProjectsPublicTaskDesc").'.'.($onlyopenedproject ? ' '.$langs->trans("OnlyOpenedProject") : '').'
'; + } + } +} +if ($mine || ($usertoprocess->id == $user->id)) { + print $langs->trans("OnlyYourTaskAreVisible").'
'; +} else { + print $langs->trans("AllTaskVisibleButEditIfYouAreAssigned").'
'; +} +print '
'; + +print dol_get_fiche_end(); + +print '
'.$nav.'
'; // We move this before the assign to components so, the default submit button is not the assign to. + +print '
'; +$titleassigntask = $langs->transnoentities("AssignTaskToMe"); +if ($usertoprocess->id != $user->id) { + $titleassigntask = $langs->transnoentities("AssignTaskToUser", $usertoprocess->getFullName($langs)); +} +print '
'; +print img_picto('', 'projecttask', 'class="pictofixedwidth"'); +$formproject->selectTasks($socid ? $socid : -1, $taskid, 'taskid', 32, 0, '-- '.$langs->trans("ChooseANotYetAssignedTask").' --', 1, 0, 0, '', '', 'all', $usertoprocess); +print '
'; +print ' '; +print $formcompany->selectTypeContact($object, '', 'type', 'internal', 'rowid', 0, 'maxwidth150onsmartphone'); +print ''; +print '
'; + +print '
'; +print $langs->trans('ShowOnlyFavoriteTasks'); +print 'global->DOLISIRH_SHOW_ONLY_FAVORITE_TASKS ? ' checked' : '').' >'; +if ($conf->global->DOLISIRH_SHOW_ONLY_FAVORITE_TASKS) { + print '
'; + print '
'.' '.$langs->trans('WarningShowOnlyFavoriteTasks').'
'; +} + + +$numendworkingday = 0; +$numstartworkingday = 0; +// Get if user is available or not for each day +$isavailable = array(); + +// Assume from Monday to Friday if conf empty or badly formed +$numstartworkingday = 1; +$numendworkingday = 5; + +if (!empty($conf->global->MAIN_DEFAULT_WORKING_DAYS)) { + $tmparray = explode('-', $conf->global->MAIN_DEFAULT_WORKING_DAYS); + if (count($tmparray) >= 2) { + $numstartworkingday = $tmparray[0]; + $numendworkingday = $tmparray[1]; + } +} + +for ($idw = 0; $idw < $dayInMonth; $idw++) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); // $firstdaytoshow is a date with hours = 0 + $dayinloopfromfirstdaytoshowgmt = dol_time_plus_duree($firstdaytoshowgmt, $idw, 'd'); // $firstdaytoshow is a date with hours = 0 + + $statusofholidaytocheck = Holiday::STATUS_APPROVED; + + $isavailablefordayanduser = $holiday->verifDateHolidayForTimestamp($usertoprocess->id, $dayinloopfromfirstdaytoshow, $statusofholidaytocheck); + $isavailable[$dayinloopfromfirstdaytoshow] = $isavailablefordayanduser; // in projectLinesPerWeek later, we are using $firstdaytoshow and dol_time_plus_duree to loop on each day + + $test = num_public_holiday($dayinloopfromfirstdaytoshowgmt, $dayinloopfromfirstdaytoshowgmt + 86400, $mysoc->country_code); + if ($test) { + $isavailable[$dayinloopfromfirstdaytoshow] = array('morning'=>false, 'afternoon'=>false, 'morning_reason'=>'public_holiday', 'afternoon_reason'=>'public_holiday'); + } +} + +$moreforfilter = ''; + +// If the user can view user other than himself +$moreforfilter .= '
'; +$moreforfilter .= '
'; +$includeonly = 'hierarchyme'; +if (empty($user->rights->user->user->lire)) { + $includeonly = array($user->id); +} +$moreforfilter .= img_picto($langs->trans('Filter').' '.$langs->trans('User'), 'user', 'class="paddingright pictofixedwidth"').$form->select_dolusers($search_usertoprocessid ? $search_usertoprocessid : $usertoprocess->id, 'search_usertoprocessid', $user->rights->user->user->lire ? 0 : 0, null, 0, $includeonly, null, 0, 0, 0, '', 0, '', 'maxwidth200'); +$moreforfilter .= '
'; + +if (empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) { + $moreforfilter .= '
'; + $moreforfilter .= '
'; + $moreforfilter .= img_picto($langs->trans('Filter').' '.$langs->trans('Project'), 'project', 'class="paddingright pictofixedwidth"').''; + $moreforfilter .= '
'; + + $moreforfilter .= '
'; + $moreforfilter .= '
'; + $moreforfilter .= img_picto($langs->trans('Filter').' '.$langs->trans('ThirdParty'), 'company', 'class="paddingright pictofixedwidth"').''; + $moreforfilter .= '
'; +} + +// Filter on categories +if (!empty($conf->categorie->enabled) && $user->rights->categorie->lire) { + $formcategory = new FormCategory($db); + $moreforfilter .= $formcategory->getFilterBox(Categorie::TYPE_PROJECT, $search_category_array); +} + +if (!empty($moreforfilter)) { + print '
'; + print $moreforfilter; + $parameters = array(); + $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + print '
'; +} + +$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; + +$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields + +// This must be after the $selectedfields +$addcolspan = 0; +if (!empty($arrayfields['t.planned_workload']['checked'])) { + $addcolspan++; +} +if (!empty($arrayfields['t.progress']['checked'])) { + $addcolspan++; +} +foreach ($arrayfields as $key => $val) { + if ($val['checked'] && substr($key, 0, 5) == 'efpt.') { + $addcolspan++; + } +} + +print '
'; +print ''."\n"; + +print ''; +if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) { + print ''; +} +if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) { + print ''; +} +print ''; +// TASK fields +$search_options_pattern = 'search_task_options_'; +$extrafieldsobjectkey = 'projet_task'; +$extrafieldsobjectprefix = 'efpt.'; +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; +if (!empty($arrayfields['t.planned_workload']['checked'])) { + print ''; +} +if (!empty($arrayfields['t.progress']['checked'])) { + print ''; +} +if (!empty($arrayfields['timeconsumed']['checked'])) { + print ''; +} +for ($idw = 0; $idw < $dayInMonth; $idw++) { + print ''; +} +// Action column +print ''; +print "\n"; + +print ''; +if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) { + print ''; +} +if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) { + print ''; +} +print ''; +// TASK fields +$extrafieldsobjectkey = 'projet_task'; +$extrafieldsobjectprefix = 'efpt.'; +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; +if (!empty($arrayfields['t.planned_workload']['checked'])) { + print ''; +} +if (!empty($arrayfields['t.progress']['checked'])) { + print ''; +} +if (!empty($arrayfields['timeconsumed']['checked'])) { + print ''; +} +for ($idw = 0; $idw < $dayInMonth; $idw++) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); // $firstdaytoshow is a date with hours = 0 + + $cssweekend = ''; + if ((($idw + 1) < $numstartworkingday) || (($idw + 1) > $numendworkingday)) { // This is a day is not inside the setup of working days, so we use a week-end css. + //$cssweekend = 'weekend'; + } + + $tmpday = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + + $cssonholiday = ''; + if (!$isavailable[$tmpday]['morning'] && !$isavailable[$tmpday]['afternoon']) { + $cssonholiday .= 'onholidayallday '; + } elseif (!$isavailable[$tmpday]['morning']) { + $cssonholiday .= 'onholidaymorning '; + } elseif (!$isavailable[$tmpday]['afternoon']) { + $cssonholiday .= 'onholidayafternoon '; + } + + print ''; +} +//print ''; +print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); + + +print "\n"; + +$colspan = 1 + (empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT) ? 0 : 2); + +$workinghours = new Workinghours($db); +$workinghoursArray = $workinghours->fetchCurrentWorkingHours($usertoprocess->id, 'user'); +$workinghoursMonth = 0; + +if ($conf->use_javascript_ajax) { + print ''; + print ''; + if (!empty($arrayfields['timeconsumed']['checked'])) { + print ''; + } + for ($idw = 0; $idw < $dayInMonth; $idw++) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + if ($isavailable[$dayinloopfromfirstdaytoshow]['morning'] && $isavailable[$dayinloopfromfirstdaytoshow]['afternoon']) { + $currentDay = date('l', $dayinloopfromfirstdaytoshow); + $currentDay = 'workinghours_' . strtolower($currentDay); + $workinghoursMonth = $workinghoursArray->{$currentDay} * 60; + } else { + $workinghoursMonth = 0; + } + + $cssweekend = ''; + if ((($idw + 1) < $numstartworkingday) || (($idw + 1) > $numendworkingday)) { // This is a day is not inside the setup of working days, so we use a week-end css. + //$cssweekend = 'weekend'; + } + + $tmpday = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + + $cssonholiday = ''; + if (!$isavailable[$tmpday]['morning'] && !$isavailable[$tmpday]['afternoon']) { + $cssonholiday .= 'onholidayallday '; + } elseif (!$isavailable[$tmpday]['morning']) { + $cssonholiday .= 'onholidaymorning '; + } elseif (!$isavailable[$tmpday]['afternoon']) { + $cssonholiday .= 'onholidayafternoon '; + } + + print ''; + } + print ''; + print ''; +} + + +// By default, we can edit only tasks we are assigned to +$restrictviewformytask = ((!isset($conf->global->PROJECT_TIME_SHOW_TASK_NOT_ASSIGNED)) ? 2 : $conf->global->PROJECT_TIME_SHOW_TASK_NOT_ASSIGNED); +if (count($tasksarray) > 0) { + //var_dump($tasksarray); // contains only selected tasks + //var_dump($tasksarraywithoutfilter); // contains all tasks (if there is a filter, not defined if no filter) + //var_dump($tasksrole); + + $j = 0; + $level = 0; + $totalforvisibletasks = projectLinesPerDayOnMonth($j, $firstdaytoshow, $lastdaytoshow, $usertoprocess, 0, $tasksarray, $level, $projectsrole, $tasksrole, $mine, $restrictviewformytask, $isavailable, 0, $arrayfields, $extrafields, $dayInMonth); + +// if (is_array($tasksarraywithoutfilter) && count($tasksarraywithoutfilter)) { +// $totalforalltasks = projectLinesPerDayOnMonth($j, $firstdaytoshow, $usertoprocess, 0, $tasksarraywithoutfilter, $level, $projectsrole, $tasksrole, $mine, $restrictviewformytask, $isavailable, 0, $arrayfields, $extrafields, $dayInMonth); +// } + //var_dump($totalforvisibletasks); + + + // Show total for all other tasks + + // Calculate total for all tasks +// $listofdistinctprojectid = array(); // List of all distinct projects +// if (is_array($tasksarraywithoutfilter) && count($tasksarraywithoutfilter)) { +// foreach ($tasksarraywithoutfilter as $tmptask) { +// $listofdistinctprojectid[$tmptask->fk_project] = $tmptask->fk_project; +// } +// } +// //var_dump($listofdistinctprojectid); +// $totalforeachday = array(); +// foreach ($listofdistinctprojectid as $tmpprojectid) { +// $projectstatic->id = $tmpprojectid; +// loadTimeSpentMonthByDay($firstdaytoshow, 0, $usertoprocess->id, $projectstatic); // Load time spent from table projet_task_time for the project into this->weekWorkLoad and this->weekWorkLoadPerTask for all days of a week +// for ($idw = 0; $idw < $dayInMonth; $idw++) { +// $tmpday = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); +// $totalforeachday[$tmpday] += $projectstatic->monthWorkLoad[$tmpday]; +// } +// } +// +// //var_dump($totalforeachday); +// //var_dump($totalforvisibletasks); +// +// // Is there a diff between selected/filtered tasks and all tasks ? +// $isdiff = 0; +// if (count($totalforeachday)) { +// for ($idw = 0; $idw < $dayInMonth; $idw++) { +// $tmpday = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); +// $timeonothertasks = ($totalforeachday[$tmpday] - $totalforvisibletasks[$tmpday]); +// if ($timeonothertasks) { +// $isdiff = 1; +// break; +// } +// } +// } +// +// // There is a diff between total shown on screen and total spent by user, so we add a line with all other cumulated time of user +// if ($isdiff) { +// print ''; +// print ''; +// if (!empty($arrayfields['timeconsumed']['checked'])) { +// print ''; +// } +// for ($idw = 0; $idw < $dayInMonth; $idw++) { +// $cssweekend = ''; +// if ((($idw + 1) < $numstartworkingday) || (($idw + 1) > $numendworkingday)) { // This is a day is not inside the setup of working days, so we use a week-end css. +// //$cssweekend = 'weekend'; +// } +// +// print ''; +// } +// print ' '; +// print ''; +// } + + if ($conf->use_javascript_ajax) { + $workinghoursMonth = 0; + print ''; + print ''; + if (!empty($arrayfields['timeconsumed']['checked'])) { + print ''; + } + + for ($idw = 0; $idw < $dayInMonthCurrent; $idw++) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + if ($isavailable[$dayinloopfromfirstdaytoshow]['morning'] && $isavailable[$dayinloopfromfirstdaytoshow]['afternoon']) { + $currentDay = date('l', $dayinloopfromfirstdaytoshow); + $currentDay = 'workinghours_' . strtolower($currentDay); + $workinghoursMonth = $workinghoursArray->{$currentDay} * 60; + } else { + $workinghoursMonth = 0; + } + + $cssweekend = ''; + if ((($idw + 1) < $numstartworkingday) || (($idw + 1) > $numendworkingday)) { // This is a day is not inside the setup of working days, so we use a week-end css. + //$cssweekend = 'weekend'; + } + + $tmpday = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + + $cssonholiday = ''; + if (!$isavailable[$tmpday]['morning'] && !$isavailable[$tmpday]['afternoon']) { + $cssonholiday .= 'onholidayallday '; + } elseif (!$isavailable[$tmpday]['morning']) { + $cssonholiday .= 'onholidaymorning '; + } elseif (!$isavailable[$tmpday]['afternoon']) { + $cssonholiday .= 'onholidayafternoon '; + } + + print ''; + } + if ($dayInMonth == $dayInMonthCurrent) { + print ''; + } + print ''; + + print ''; + print ''; + if (!empty($arrayfields['timeconsumed']['checked'])) { + print ''; + } + + for ($idw = 0; $idw < $dayInMonthCurrent; $idw++) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + if ($isavailable[$dayinloopfromfirstdaytoshow]['morning'] && $isavailable[$dayinloopfromfirstdaytoshow]['afternoon']) { + $currentDay = date('l', $dayinloopfromfirstdaytoshow); + $currentDay = 'workinghours_' . strtolower($currentDay); + $workinghoursMonth = $workinghoursArray->{$currentDay} * 60; + } else { + $workinghoursMonth = 0; + } + + $cssweekend = ''; + if ((($idw + 1) < $numstartworkingday) || (($idw + 1) > $numendworkingday)) { // This is a day is not inside the setup of working days, so we use a week-end css. + //$cssweekend = 'weekend'; + } + + $tmpday = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + + $cssonholiday = ''; + if (!$isavailable[$tmpday]['morning'] && !$isavailable[$tmpday]['afternoon']) { + $cssonholiday .= 'onholidayallday '; + } elseif (!$isavailable[$tmpday]['morning']) { + $cssonholiday .= 'onholidaymorning '; + } elseif (!$isavailable[$tmpday]['afternoon']) { + $cssonholiday .= 'onholidayafternoon '; + } + + print ''; + } + if ($dayInMonth == $dayInMonthCurrent) { + print ''; + } + print ''; + + print ''; + print ''; + if (!empty($arrayfields['timeconsumed']['checked'])) { + print ''; + } + + for ($idw = 0; $idw < $dayInMonthCurrent; $idw++) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + if ($isavailable[$dayinloopfromfirstdaytoshow]['morning'] && $isavailable[$dayinloopfromfirstdaytoshow]['afternoon']) { + $currentDay = date('l', $dayinloopfromfirstdaytoshow); + $currentDay = 'workinghours_' . strtolower($currentDay); + $workinghoursMonth = $workinghoursArray->{$currentDay} * 60; + } else { + $workinghoursMonth = 0; + } + $difftime = $workinghoursMonth - $totalforvisibletasks[$dayinloopfromfirstdaytoshow]; + if ($difftime < 0) { + $morecss = colorStringToArray($conf->global->DOLISIRH_EXCEEDED_TIME_SPENT_COLOR); + } else if ($difftime > 0) { + $morecss = colorStringToArray($conf->global->DOLISIRH_NOT_EXCEEDED_TIME_SPENT_COLOR); + } else if ($difftime == 0) { + $morecss = colorStringToArray($conf->global->DOLISIRH_PERFECT_TIME_SPENT_COLOR); + } + $cssweekend = ''; + if ((($idw + 1) < $numstartworkingday) || (($idw + 1) > $numendworkingday)) { // This is a day is not inside the setup of working days, so we use a week-end css. + //$cssweekend = 'weekend'; + } + + $tmpday = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + + $cssonholiday = ''; + if (!$isavailable[$tmpday]['morning'] && !$isavailable[$tmpday]['afternoon']) { + $cssonholiday .= 'onholidayallday '; + } elseif (!$isavailable[$tmpday]['morning']) { + $cssonholiday .= 'onholidaymorning '; + } elseif (!$isavailable[$tmpday]['afternoon']) { + $cssonholiday .= 'onholidayafternoon '; + } + + print ''; + } + if ($dayInMonth == $dayInMonthCurrent) { + print ''; + } + print ''; + } +} else { + print ''; +} +print "
'; +$searchpicto = $form->showFilterAndCheckAddButtons(0); +print $searchpicto; +print '
'.$langs->trans("Project").''.$langs->trans("ThirdParty").''.$langs->trans("Task").''.$langs->trans("PlannedWorkload").''.$langs->trans("ProgressDeclared").''.$langs->trans("TimeSpent").($usertoprocess->firstname ? '
'.$usertoprocess->getNomUrl(-2).''.dol_trunc($usertoprocess->firstname, 10).'' : '').'
'; + print dol_print_date($dayinloopfromfirstdaytoshow, '%a'); + $splitted_date = preg_split('/\//', dol_print_date($dayinloopfromfirstdaytoshow, "day")); + $day = $splitted_date[0]; + $month = $splitted_date[1]; + $year = $splitted_date[2]; + print ' '; + print '
'.dol_print_date($dayinloopfromfirstdaytoshow, '%d/%m').'
'; + print $langs->trans("Total"); + for ($idw = 0; $idw < $dayInMonth; $idw++) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + if ($isavailable[$dayinloopfromfirstdaytoshow]['morning'] && $isavailable[$dayinloopfromfirstdaytoshow]['afternoon']) { + $currentDay = date('l', $dayinloopfromfirstdaytoshow); + $currentDay = 'workinghours_' . strtolower($currentDay); + $workinghoursMonth += $workinghoursArray->{$currentDay} * 60; + } + } + print ' - '.$langs->trans("ExpectedWorkedHoursMonth", dol_print_date(dol_mktime(0, 0, 0, $month, $day, $year), "%B %Y")).' : '.(($workinghoursMonth != 0) ? convertSecondToTime($workinghoursMonth, 'allhourmin') : '00:00').''; + print '
'.(($workinghoursMonth != 0) ? convertSecondToTime($workinghoursMonth, 'allhourmin') : '00:00').'
'; +// print $langs->trans("OtherFilteredTasks"); +// print '
 
'; +// $tmpday = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); +// $timeonothertasks = ($totalforeachday[$tmpday] - $totalforvisibletasks[$tmpday]); +// if ($timeonothertasks) { +// print ''; +// } +// print '
'; + print $langs->trans("Total"); + + $currentDayCurrent = date( 'd', $now); + $currentMonth = date( 'm', $now); + + if ($currentMonth == $month) { + $dayInMonthCurrent = $currentDayCurrent; + } else { + $dayInMonthCurrent = $dayInMonth; + } + + for ($idw = 0; $idw < $dayInMonthCurrent; $idw++) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + if ($isavailable[$dayinloopfromfirstdaytoshow]['morning'] && $isavailable[$dayinloopfromfirstdaytoshow]['afternoon']) { + $currentDay = date('l', $dayinloopfromfirstdaytoshow); + $currentDay = 'workinghours_' . strtolower($currentDay); + $workinghoursMonth += $workinghoursArray->{$currentDay} * 60; + } + } + $totalspenttime = $workinghoursMonth/60/60; + print ' - '.$langs->trans("SpentWorkedHoursMonth", dol_print_date($firstdaytoshow, "dayreduceformat"), (($dayInMonth == $dayInMonthCurrent) ? dol_print_date($lastdaytoshow, "dayreduceformat") : dol_print_date($now, "dayreduceformat"))).' : '.(($workinghoursMonth != 0) ? convertSecondToTime($workinghoursMonth, 'allhourmin') : '00:00').''; + print '
'.(($workinghoursMonth != 0) ? convertSecondToTime($workinghoursMonth, 'allhourmin') : '00:00').'
'; + print $langs->trans("Total"); + + foreach ($totalforvisibletasks as $task) { + $totalconsumedtime += $task; + } + print ' - '.$langs->trans("ConsumedWorkedHoursMonth", dol_print_date($firstdaytoshow, "dayreduceformat"), (($dayInMonth == $dayInMonthCurrent) ? dol_print_date($lastdaytoshow, "dayreduceformat") : dol_print_date($now, "dayreduceformat"))).' : '.convertSecondToTime($totalconsumedtime, 'allhourmin').''; + print ''.convertSecondToTime($totalconsumedtime, 'allhourmin').'
'.dol_print_date($workinghoursMonth, 'hour').'
'; + print $langs->trans("Total"); + $difftotaltime = $totalspenttime * 60 * 60 - $totalconsumedtime; + if ($difftotaltime < 0) { + $morecss = colorStringToArray($conf->global->DOLISIRH_EXCEEDED_TIME_SPENT_COLOR); + } else if ($difftotaltime > 0) { + $morecss = colorStringToArray($conf->global->DOLISIRH_NOT_EXCEEDED_TIME_SPENT_COLOR); + } else if ($difftotaltime == 0) { + $morecss = colorStringToArray($conf->global->DOLISIRH_PERFECT_TIME_SPENT_COLOR); + } + print ' - '.$langs->trans("DiffSpentAndConsumedWorkedHoursMonth", dol_print_date($firstdaytoshow, "dayreduceformat"), (($dayInMonth == $dayInMonthCurrent) ? dol_print_date($lastdaytoshow, "dayreduceformat") : dol_print_date($now, "dayreduceformat"))).' : '.(($difftotaltime != 0) ? convertSecondToTime(abs($difftotaltime), 'allhourmin') : '00:00').''; + print ''.(($difftotaltime != 0) ? convertSecondToTime(abs($difftotaltime), 'allhourmin') : '00:00').'
'.(($difftime != 0) ? convertSecondToTime(abs($difftime), 'allhourmin') : '00:00').'
'.$langs->trans("NoAssignedTasks").'
"; +print '
'; + +print ''."\n"; + +print $form->buttonsSaveCancel("Save", ''); + +print '
'."\n\n"; + +$modeinput = 'hours'; + +if ($conf->use_javascript_ajax) { + print "\n\n"; + print ''; +} + +// End of page +llxFooter(); +$db->close(); diff --git a/view/timespent_week.php b/view/timespent_week.php new file mode 100644 index 0000000..91aed14 --- /dev/null +++ b/view/timespent_week.php @@ -0,0 +1,1087 @@ + + * Copyright (C) 2004-2015 Laurent Destailleur + * Copyright (C) 2005-2010 Regis Houssin + * Copyright (C) 2010 François Legastelois + * Copyright (C) 2018 Frédéric France + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/projet/activity/perweek.php + * \ingroup projet + * \brief List activities of tasks (per week entry) + */ + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if ( ! $res && ! empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"] . "/main.inc.php"; +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } +if ( ! $res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1)) . "/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1)) . "/main.inc.php"; +if ( ! $res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1))) . "/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1))) . "/main.inc.php"; +// Try main.inc.php using relative path +if ( ! $res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; +if ( ! $res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; +if ( ! $res) die("Include of main fails"); + +// Libraries +require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; +require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/project.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'; +require_once DOL_DOCUMENT_ROOT.'/holiday/class/holiday.class.php'; +if (!empty($conf->categorie->enabled)) { + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcategory.class.php'; + require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; +} + +require_once DOL_DOCUMENT_ROOT.'/custom/dolisirh/lib/dolisirh_function.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/custom/dolisirh/class/workinghours.class.php'; + +// Global variables definitions +global $conf, $db, $hookmanager, $langs, $user; + +// Load translation files required by the page +$langs->loadLangs(array('projects', 'users', 'companies')); + +// Get parameters +$action = GETPOST('action', 'aZ09'); +$mode = GETPOST("mode", 'alpha'); +$id = GETPOST('id', 'int'); +$taskid = GETPOST('taskid', 'int'); +$contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'perweekcard'; + +$mine = 0; +if ($mode == 'mine') { + $mine = 1; +} + +$projectid = GETPOSTISSET("id") ? GETPOST("id", "int", 1) : GETPOST("projectid", "int"); + +$hookmanager->initHooks(array('timesheetperweekcard')); + +// Security check +$socid = 0; +// For external user, no check is done on company because readability is managed by public status of project and assignement. +// if ($user->socid > 0) $socid=$user->socid; +$result = restrictedArea($user, 'projet', $projectid); + +$now = dol_now(); + +$year = GETPOST('reyear', 'int') ?GETPOST('reyear', 'int') : (GETPOST("year", 'int') ?GETPOST("year", "int") : date("Y")); +$month = GETPOST('remonth', 'int') ?GETPOST('remonth', 'int') : (GETPOST("month", 'int') ?GETPOST("month", "int") : date("m")); +$day = GETPOST('reday', 'int') ?GETPOST('reday', 'int') : (GETPOST("day", 'int') ?GETPOST("day", "int") : date("d")); +$week = GETPOST("week", "int") ?GETPOST("week", "int") : date("W"); + +$day = (int) $day; + +$search_usertoprocessid = GETPOST('search_usertoprocessid', 'int'); +$search_task_ref = GETPOST('search_task_ref', 'alpha'); +$search_task_label = GETPOST('search_task_label', 'alpha'); +$search_project_ref = GETPOST('search_project_ref', 'alpha'); +$search_thirdparty = GETPOST('search_thirdparty', 'alpha'); +$search_declared_progress = GETPOST('search_declared_progress', 'alpha'); + +if (!empty($conf->categorie->enabled)) { + $search_category_array = GETPOST("search_category_".Categorie::TYPE_PROJECT."_list", "array"); +} + + +$sortfield = GETPOST('sortfield', 'aZ09comma'); +$sortorder = GETPOST('sortorder', 'aZ09comma'); + +$startdayarray = dol_get_first_day_week($day, $month, $year); + +$prev = $startdayarray; +$prev_year = $prev['prev_year']; +$prev_month = $prev['prev_month']; +$prev_day = $prev['prev_day']; +$first_day = $prev['first_day']; +$first_month = $prev['first_month']; +$first_year = $prev['first_year']; +$week = $prev['week']; + +$next = dol_get_next_week($first_day, $week, $first_month, $first_year); +$next_year = $next['year']; +$next_month = $next['month']; +$next_day = $next['day']; + +// Define firstdaytoshow and lastdaytoshow (warning: lastdaytoshow is last second to show + 1) +$firstdaytoshow = dol_mktime(0, 0, 0, $first_month, $first_day, $first_year); +$firstdaytoshowgmt = dol_mktime(0, 0, 0, $first_month, $first_day, $first_year, 'gmt'); + +if (empty($search_usertoprocessid) || $search_usertoprocessid == $user->id) { + $usertoprocess = $user; + $search_usertoprocessid = $usertoprocess->id; +} elseif ($search_usertoprocessid > 0) { + $usertoprocess = new User($db); + $usertoprocess->fetch($search_usertoprocessid); + $search_usertoprocessid = $usertoprocess->id; +} else { + $usertoprocess = new User($db); +} + +$object = new Task($db); + +// Extra fields +$extrafields = new ExtraFields($db); + +// fetch optionals attributes and labels +$extrafields->fetch_name_optionals_label($object->table_element); + +// Definition of fields for list +$arrayfields = array(); +/*$arrayfields=array( + // Project + 'p.opp_amount'=>array('label'=>$langs->trans("OpportunityAmountShort"), 'checked'=>0, 'enabled'=>($conf->global->PROJECT_USE_OPPORTUNITIES?1:0), 'position'=>103), + 'p.fk_opp_status'=>array('label'=>$langs->trans("OpportunityStatusShort"), 'checked'=>0, 'enabled'=>($conf->global->PROJECT_USE_OPPORTUNITIES?1:0), 'position'=>104), + 'p.opp_percent'=>array('label'=>$langs->trans("OpportunityProbabilityShort"), 'checked'=>0, 'enabled'=>($conf->global->PROJECT_USE_OPPORTUNITIES?1:0), 'position'=>105), + 'p.budget_amount'=>array('label'=>$langs->trans("Budget"), 'checked'=>0, 'position'=>110), + 'p.usage_bill_time'=>array('label'=>$langs->trans("BillTimeShort"), 'checked'=>0, 'position'=>115), + );*/ +//$arrayfields['t.planned_workload'] = array('label'=>'PlannedWorkload', 'checked'=>1, 'enabled'=>1, 'position'=>5); +//$arrayfields['t.progress'] = array('label'=>'ProgressDeclared', 'checked'=>1, 'enabled'=>1, 'position'=>10); +$arrayfields['timeconsumed'] = array('label'=>'TimeConsumed', 'checked'=>1, 'enabled'=>1, 'position'=>15); +/*foreach($object->fields as $key => $val) + { + // If $val['visible']==0, then we never show the field + if (! empty($val['visible'])) $arrayfields['t.'.$key]=array('label'=>$val['label'], 'checked'=>(($val['visible']<0)?0:1), 'enabled'=>$val['enabled'], 'position'=>$val['position']); + }*/ +// Definition of fields for list +// Extra fields +if (!empty($extrafields->attributes['projet_task']['label']) && is_array($extrafields->attributes['projet_task']['label']) && count($extrafields->attributes['projet_task']['label']) > 0) { + foreach ($extrafields->attributes['projet_task']['label'] as $key => $val) { + if (!empty($extrafields->attributes['projet_task']['list'][$key])) { + $arrayfields["efpt.".$key] = array('label'=>$extrafields->attributes['projet_task']['label'][$key], 'checked'=>(($extrafields->attributes['projet_task']['list'][$key] < 0) ? 0 : 1), 'position'=>$extrafields->attributes['projet_task']['pos'][$key], 'enabled'=>(abs((int) $extrafields->attributes['projet_task']['list'][$key]) != 3 && $extrafields->attributes['projet_task']['perms'][$key])); + } + } +} +$arrayfields = dol_sort_array($arrayfields, 'position'); + +$search_array_options = array(); +$search_array_options_project = $extrafields->getOptionalsFromPost('projet', '', 'search_'); +$search_array_options_task = $extrafields->getOptionalsFromPost('projet_task', '', 'search_task_'); + + + +/* + * Actions + */ + +$parameters = array('id' => $id, 'taskid' => $taskid, 'projectid' => $projectid); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} +// Purge criteria +if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers + $action = ''; + $search_usertoprocessid = $user->id; + $search_task_ref = ''; + $search_task_label = ''; + $search_project_ref = ''; + $search_thirdparty = ''; + $search_declared_progress = ''; + + $search_array_options_project = array(); + $search_array_options_task = array(); + $search_category_array = array(); + + // We redefine $usertoprocess + $usertoprocess = $user; +} +if (GETPOST("button_search_x", 'alpha') || GETPOST("button_search.x", 'alpha') || GETPOST("button_search", 'alpha')) { + $action = ''; +} + +if (GETPOST('submitdateselect')) { + if (GETPOST('remonth', 'int') && GETPOST('reday', 'int') && GETPOST('reyear', 'int')) { + $daytoparse = dol_mktime(0, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int')); + } + + $action = ''; +} + +include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php'; + +if ($action == 'addtime' && $user->rights->projet->lire && GETPOST('assigntask') && GETPOST('formfilteraction') != 'listafterchangingselectedfields') { + $action = 'assigntask'; + + if ($taskid > 0) { + $result = $object->fetch($taskid, $ref); + if ($result < 0) { + $error++; + } + } else { + setEventMessages($langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Task")), '', 'errors'); + $error++; + } + if (!GETPOST('type')) { + setEventMessages($langs->transnoentitiesnoconv("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), '', 'errors'); + $error++; + } + + if (!$error) { + $idfortaskuser = $usertoprocess->id; + $result = $object->add_contact($idfortaskuser, GETPOST("type"), 'internal'); + + if ($result >= 0 || $result == -2) { // Contact add ok or already contact of task + // Test if we are already contact of the project (should be rare but sometimes we can add as task contact without being contact of project, like when admin user has been removed from contact of project) + $sql = 'SELECT ec.rowid FROM '.MAIN_DB_PREFIX.'element_contact as ec, '.MAIN_DB_PREFIX.'c_type_contact as tc WHERE tc.rowid = ec.fk_c_type_contact'; + $sql .= ' AND ec.fk_socpeople = '.((int) $idfortaskuser)." AND ec.element_id = ".((int) $object->fk_project)." AND tc.element = 'project' AND source = 'internal'"; + $resql = $db->query($sql); + if ($resql) { + $obj = $db->fetch_object($resql); + if (!$obj) { // User is not already linked to project, so we will create link to first type + $project = new Project($db); + $project->fetch($object->fk_project); + // Get type + $listofprojcontact = $project->liste_type_contact('internal'); + + if (count($listofprojcontact)) { + $typeforprojectcontact = reset(array_keys($listofprojcontact)); + $result = $project->add_contact($idfortaskuser, $typeforprojectcontact, 'internal'); + } + } + } else { + dol_print_error($db); + } + } + } + + if ($result < 0) { + $error++; + if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') { + $langs->load("errors"); + setEventMessages($langs->trans("ErrorTaskAlreadyAssigned"), null, 'warnings'); + } else { + setEventMessages($object->error, $object->errors, 'errors'); + } + } + + if (!$error) { + setEventMessages("TaskAssignedToEnterTime", null); + $taskid = 0; + } + + $action = ''; +} + +if ($action == 'addtime' && $user->rights->projet->lire && GETPOST('formfilteraction') != 'listafterchangingselectedfields') { + $timetoadd = $_POST['task']; + if (empty($timetoadd)) { + setEventMessages($langs->trans("ErrorTimeSpentIsEmpty"), null, 'errors'); + } else { + foreach ($timetoadd as $taskid => $value) { // Loop on each task + $updateoftaskdone = 0; + foreach ($value as $key => $val) { // Loop on each day + $amountoadd = $timetoadd[$taskid][$key]; + if (!empty($amountoadd)) { + $tmpduration = explode(':', $amountoadd); + $newduration = 0; + if (!empty($tmpduration[0])) { + $newduration += ($tmpduration[0] * 3600); + } + if (!empty($tmpduration[1])) { + $newduration += ($tmpduration[1] * 60); + } + if (!empty($tmpduration[2])) { + $newduration += ($tmpduration[2]); + } + + if ($newduration > 0) { + $object->fetch($taskid); + + if (GETPOSTISSET($taskid.'progress')) { + $object->progress = GETPOST($taskid.'progress', 'int'); + } else { + unset($object->progress); + } + + $object->timespent_duration = $newduration; + $object->timespent_fk_user = $usertoprocess->id; + $object->timespent_date = dol_time_plus_duree($firstdaytoshow, $key, 'd'); + $object->timespent_datehour = $object->timespent_date; + $object->timespent_note = $object->description; + + $result = $object->addTimeSpent($user); + if ($result < 0) { + setEventMessages($object->error, $object->errors, 'errors'); + $error++; + break; + } + + $updateoftaskdone++; + } + } + } + + if (!$updateoftaskdone) { // Check to update progress if no update were done on task. + $object->fetch($taskid); + //var_dump($object->progress);var_dump(GETPOST($taskid . 'progress', 'int')); exit; + if ($object->progress != GETPOST($taskid.'progress', 'int')) { + $object->progress = GETPOST($taskid.'progress', 'int'); + $result = $object->update($user); + if ($result < 0) { + setEventMessages($object->error, $object->errors, 'errors'); + $error++; + break; + } + } + } + } + + if (!$error) { + setEventMessages($langs->trans("RecordSaved"), null, 'mesgs'); + + $param = ''; + $param .= ($mode ? '&mode='.urlencode($mode) : ''); + $param .= ($projectid ? 'id='.urlencode($projectid) : ''); + $param .= ($search_usertoprocessid ? '&search_usertoprocessid='.urlencode($search_usertoprocessid) : ''); + $param .= ($day ? '&day='.urlencode($day) : '').($month ? '&month='.urlencode($month) : '').($year ? '&year='.urlencode($year) : ''); + $param .= ($search_project_ref ? '&search_project_ref='.urlencode($search_project_ref) : ''); + $param .= ($search_usertoprocessid > 0 ? '&search_usertoprocessid='.urlencode($search_usertoprocessid) : ''); + $param .= ($search_thirdparty ? '&search_thirdparty='.urlencode($search_thirdparty) : ''); + $param .= ($search_declared_progress ? '&search_declared_progress='.urlencode($search_declared_progress) : ''); + $param .= ($search_task_ref ? '&search_task_ref='.urlencode($search_task_ref) : ''); + $param .= ($search_task_label ? '&search_task_label='.urlencode($search_task_label) : ''); + + /*$search_array_options=$search_array_options_project; + $search_options_pattern='search_options_'; + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; + */ + + $search_array_options = $search_array_options_task; + $search_options_pattern = 'search_task_options_'; + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; + + // Redirect to avoid submit twice on back + header('Location: '.$_SERVER["PHP_SELF"].'?'.$param); + exit; + } + } +} + +if ($action == 'showOnlyFavoriteTasks') { + if ($conf->global->DOLISIRH_SHOW_ONLY_FAVORITE_TASKS == 1) { + dolibarr_set_const($db, 'DOLISIRH_SHOW_ONLY_FAVORITE_TASKS', 0, 'integer', 0, '', $conf->entity); + } else { + dolibarr_set_const($db, 'DOLISIRH_SHOW_ONLY_FAVORITE_TASKS', 1, 'integer', 0, '', $conf->entity); + } +} + +/* + * View + */ + +$form = new Form($db); +$formother = new FormOther($db); +$formcompany = new FormCompany($db); +$formproject = new FormProjets($db); +$projectstatic = new Project($db); +$project = new Project($db); +$taskstatic = new Task($db); +$thirdpartystatic = new Societe($db); +$holiday = new Holiday($db); + +$title = $langs->trans("TimeSpent"); +$help_url = ''; +$morejs = array("/dolisirh/js/dolisirh.js.php", "/core/js/timesheet.js"); +$morecss = array("/dolisirh/css/dolisirh.css"); + +$projectsListId = $projectstatic->getProjectsAuthorizedForUser($usertoprocess, (empty($usertoprocess->id) ? 2 : 0), 1); // Return all project i have permission on (assigned to me+public). I want my tasks and some of my task may be on a public projet that is not my project +//var_dump($projectsListId); +if ($id) { + $project->fetch($id); + $project->fetch_thirdparty(); +} + +$onlyopenedproject = 1; // or -1 +$morewherefilter = ''; + +if ($search_project_ref) { + $morewherefilter .= natural_search(array("p.ref", "p.title"), $search_project_ref); +} +if ($search_task_ref) { + $morewherefilter .= natural_search("t.ref", $search_task_ref); +} +if ($search_task_label) { + $morewherefilter .= natural_search(array("t.ref", "t.label"), $search_task_label); +} +if ($search_thirdparty) { + $morewherefilter .= natural_search("s.nom", $search_thirdparty); +} +if ($search_declared_progress) { + $morewherefilter .= natural_search("t.progress", $search_declared_progress, 1); +} +if (!empty($conf->categorie->enabled)) { + $morewherefilter .= Categorie::getFilterSelectQuery(Categorie::TYPE_PROJECT, "p.rowid", $search_category_array); +} + +$sql = &$morewherefilter; + +/*$search_array_options = $search_array_options_project; + $extrafieldsobjectprefix='efp.'; + $search_options_pattern='search_options_'; + $extrafieldsobjectkey='projet'; + include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; + */ +$search_array_options = $search_array_options_task; +$extrafieldsobjectprefix = 'efpt.'; +$search_options_pattern = 'search_task_options_'; +$extrafieldsobjectkey = 'projet_task'; +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; + +$tasksarray = $taskstatic->getTasksArray( 0, 0, ($project->id ? $project->id : 0), $socid, 0, $search_project_ref, $onlyopenedproject, $morewherefilter, ($search_usertoprocessid ? $search_usertoprocessid : 0), 0, $extrafields); // We want to see all tasks of open project i am allowed to see and that match filter, not only my tasks. Later only mine will be editable later. +if ($morewherefilter) { // Get all task without any filter, so we can show total of time spent for not visible tasks + $tasksarraywithoutfilter = getFavoriteTasksArray($taskstatic->id, 0, 0, ($project->id ? $project->id : 0), $socid, 0, '', $onlyopenedproject, '', ($search_usertoprocessid ? $search_usertoprocessid : 0)); // We want to see all tasks of open project i am allowed to see and that match filter, not only my tasks. Later only mine will be editable later. +} +$projectsrole = $taskstatic->getUserRolesForProjectsOrTasks($usertoprocess, 0, ($project->id ? $project->id : 0), 0, $onlyopenedproject); +$tasksrole = $taskstatic->getUserRolesForProjectsOrTasks(0, $usertoprocess, ($project->id ? $project->id : 0), 0, $onlyopenedproject); +//var_dump($tasksarray); +//var_dump($projectsrole); +//var_dump($taskrole); + + +llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss); + +//print_barre_liste($title, $page, $_SERVER["PHP_SELF"], "", $sortfield, $sortorder, "", $num, '', 'project'); + +$param = ''; +$param .= ($mode ? '&mode='.urlencode($mode) : ''); +$param .= ($search_project_ref ? '&search_project_ref='.urlencode($search_project_ref) : ''); +$param .= ($search_usertoprocessid > 0 ? '&search_usertoprocessid='.urlencode($search_usertoprocessid) : ''); +$param .= ($search_thirdparty ? '&search_thirdparty='.urlencode($search_thirdparty) : ''); +$param .= ($search_task_ref ? '&search_task_ref='.urlencode($search_task_ref) : ''); +$param .= ($search_task_label ? '&search_task_label='.urlencode($search_task_label) : ''); + +$search_array_options = $search_array_options_project; +$search_options_pattern = 'search_options_'; +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; + +$search_array_options = $search_array_options_task; +$search_options_pattern = 'search_task_options_'; +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; + +// Show navigation bar +$nav = ''.img_previous($langs->trans("Previous"))."\n"; +$nav .= ' '.dol_print_date(dol_mktime(0, 0, 0, $first_month, $first_day, $first_year), "%Y").", ".$langs->trans("WeekShort")." ".$week." \n"; +$nav .= ''.img_next($langs->trans("Next"))."\n"; +$nav .= ' '.$form->selectDate(-1, '', 0, 0, 2, "addtime", 1, 1).' '; +$nav .= ' '; + +$picto = 'clock'; + +print '
'; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +$head = dolisirh_timesheet_prepare_head($mode, $usertoprocess); +print dol_get_fiche_head($head, 'inputperweek', $langs->trans('TimeSpent'), -1, $picto); + +// Show description of content +print '
'; +if ($mine || ($usertoprocess->id == $user->id)) { + print $langs->trans("MyTasksDesc").'.'.($onlyopenedproject ? ' '.$langs->trans("OnlyOpenedProject") : '').'
'; +} else { + if (empty($usertoprocess->id) || $usertoprocess->id < 0) { + if ($user->rights->projet->all->lire && !$socid) { + print $langs->trans("ProjectsDesc").'.'.($onlyopenedproject ? ' '.$langs->trans("OnlyOpenedProject") : '').'
'; + } else { + print $langs->trans("ProjectsPublicTaskDesc").'.'.($onlyopenedproject ? ' '.$langs->trans("OnlyOpenedProject") : '').'
'; + } + } +} +if ($mine || ($usertoprocess->id == $user->id)) { + print $langs->trans("OnlyYourTaskAreVisible").'
'; +} else { + print $langs->trans("AllTaskVisibleButEditIfYouAreAssigned").'
'; +} +print '
'; + +print dol_get_fiche_end(); + +print '
'.$nav.'
'; // We move this before the assign to components so, the default submit button is not the assign to. + +print '
'; +$titleassigntask = $langs->transnoentities("AssignTaskToMe"); +if ($usertoprocess->id != $user->id) { + $titleassigntask = $langs->transnoentities("AssignTaskToUser", $usertoprocess->getFullName($langs)); +} +print '
'; +print img_picto('', 'projecttask', 'class="pictofixedwidth"'); +$formproject->selectTasks($socid ? $socid : -1, $taskid, 'taskid', 32, 0, '-- '.$langs->trans("ChooseANotYetAssignedTask").' --', 1, 0, 0, '', '', 'all', $usertoprocess); +print '
'; +print ' '; +print $formcompany->selectTypeContact($object, '', 'type', 'internal', 'rowid', 0, 'maxwidth150onsmartphone'); +print ''; +print '
'; + +print '
'; +print $langs->trans('ShowOnlyFavoriteTasks'); +print 'global->DOLISIRH_SHOW_ONLY_FAVORITE_TASKS ? ' checked' : '').' >'; +if ($conf->global->DOLISIRH_SHOW_ONLY_FAVORITE_TASKS) { + print '
'; + print '
'.' '.$langs->trans('WarningShowOnlyFavoriteTasks').'
'; +} + +$startday = dol_mktime(12, 0, 0, $startdayarray['first_month'], $startdayarray['first_day'], $startdayarray['first_year']); + +$numendworkingday = 0; +$numstartworkingday = 0; +// Get if user is available or not for each day +$isavailable = array(); + +// Assume from Monday to Friday if conf empty or badly formed +$numstartworkingday = 1; +$numendworkingday = 5; + +if (!empty($conf->global->MAIN_DEFAULT_WORKING_DAYS)) { + $tmparray = explode('-', $conf->global->MAIN_DEFAULT_WORKING_DAYS); + if (count($tmparray) >= 2) { + $numstartworkingday = $tmparray[0]; + $numendworkingday = $tmparray[1]; + } +} + +for ($idw = 0; $idw < 7; $idw++) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); // $firstdaytoshow is a date with hours = 0 + $dayinloopfromfirstdaytoshowgmt = dol_time_plus_duree($firstdaytoshowgmt, $idw, 'd'); // $firstdaytoshow is a date with hours = 0 + + $statusofholidaytocheck = Holiday::STATUS_APPROVED; + + $isavailablefordayanduser = $holiday->verifDateHolidayForTimestamp($usertoprocess->id, $dayinloopfromfirstdaytoshow, $statusofholidaytocheck); + $isavailable[$dayinloopfromfirstdaytoshow] = $isavailablefordayanduser; // in projectLinesPerWeek later, we are using $firstdaytoshow and dol_time_plus_duree to loop on each day + + $test = num_public_holiday($dayinloopfromfirstdaytoshowgmt, $dayinloopfromfirstdaytoshowgmt + 86400, $mysoc->country_code); + if ($test) { + $isavailable[$dayinloopfromfirstdaytoshow] = array('morning'=>false, 'afternoon'=>false, 'morning_reason'=>'public_holiday', 'afternoon_reason'=>'public_holiday'); + } +} + + + +$moreforfilter = ''; + +// If the user can view user other than himself +$moreforfilter .= '
'; +$moreforfilter .= '
'; +$includeonly = 'hierarchyme'; +if (empty($user->rights->user->user->lire)) { + $includeonly = array($user->id); +} +$moreforfilter .= img_picto($langs->trans('Filter').' '.$langs->trans('User'), 'user', 'class="paddingright pictofixedwidth"').$form->select_dolusers($search_usertoprocessid ? $search_usertoprocessid : $usertoprocess->id, 'search_usertoprocessid', $user->rights->user->user->lire ? 0 : 0, null, 0, $includeonly, null, 0, 0, 0, '', 0, '', 'maxwidth200'); +$moreforfilter .= '
'; + +if (empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) { + $moreforfilter .= '
'; + $moreforfilter .= '
'; + $moreforfilter .= img_picto($langs->trans('Filter').' '.$langs->trans('Project'), 'project', 'class="paddingright pictofixedwidth"').''; + $moreforfilter .= '
'; + + $moreforfilter .= '
'; + $moreforfilter .= '
'; + $moreforfilter .= img_picto($langs->trans('Filter').' '.$langs->trans('ThirdParty'), 'company', 'class="paddingright pictofixedwidth"').''; + $moreforfilter .= '
'; +} + +// Filter on categories +if (!empty($conf->categorie->enabled) && $user->rights->categorie->lire) { + $formcategory = new FormCategory($db); + $moreforfilter .= $formcategory->getFilterBox(Categorie::TYPE_PROJECT, $search_category_array); +} + +if (!empty($moreforfilter)) { + print '
'; + print $moreforfilter; + $parameters = array(); + $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; + print '
'; +} + + +$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; + +$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields + +// This must be after the $selectedfields +$addcolspan = 0; +if (!empty($arrayfields['t.planned_workload']['checked'])) { + $addcolspan++; +} +if (!empty($arrayfields['t.progress']['checked'])) { + $addcolspan++; +} +foreach ($arrayfields as $key => $val) { + if ($val['checked'] && substr($key, 0, 5) == 'efpt.') { + $addcolspan++; + } +} + +print '
'; +print ''."\n"; + +print ''; +if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) { + print ''; +} +if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) { + print ''; +} +print ''; +// TASK fields +$search_options_pattern = 'search_task_options_'; +$extrafieldsobjectkey = 'projet_task'; +$extrafieldsobjectprefix = 'efpt.'; +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php'; +if (!empty($arrayfields['t.planned_workload']['checked'])) { + print ''; +} +if (!empty($arrayfields['t.progress']['checked'])) { + print ''; +} +if (!empty($arrayfields['timeconsumed']['checked'])) { + print ''; + print ''; +} +for ($idw = 0; $idw < 7; $idw++) { + print ''; +} +// Action column +print ''; +print "\n"; + +print ''; +if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) { + print ''; +} +if (!empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT)) { + print ''; +} +print ''; +// TASK fields +$extrafieldsobjectkey = 'projet_task'; +$extrafieldsobjectprefix = 'efpt.'; +include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; +if (!empty($arrayfields['t.planned_workload']['checked'])) { + print ''; +} +if (!empty($arrayfields['t.progress']['checked'])) { + print ''; +} +if (!empty($arrayfields['timeconsumed']['checked'])) { + print ''; + print ''; +} +for ($idw = 0; $idw < 7; $idw++) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); // $firstdaytoshow is a date with hours = 0 + + $cssweekend = ''; + if ((($idw + 1) < $numstartworkingday) || (($idw + 1) > $numendworkingday)) { // This is a day is not inside the setup of working days, so we use a week-end css. + $cssweekend = 'weekend'; + } + + $tmpday = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + + $cssonholiday = ''; + if (!$isavailable[$tmpday]['morning'] && !$isavailable[$tmpday]['afternoon']) { + $cssonholiday .= 'onholidayallday '; + } elseif (!$isavailable[$tmpday]['morning']) { + $cssonholiday .= 'onholidaymorning '; + } elseif (!$isavailable[$tmpday]['afternoon']) { + $cssonholiday .= 'onholidayafternoon '; + } + + print ''; +} +//print ''; +print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); + + +print "\n"; + +$colspan = 1 + (empty($conf->global->PROJECT_TIMESHEET_DISABLEBREAK_ON_PROJECT) ? 0 : 2); + +$workinghours = new Workinghours($db); +$workinghoursArray = $workinghours->fetchCurrentWorkingHours($usertoprocess->id, 'user'); +$workinghoursWeek = 0; + +if ($conf->use_javascript_ajax) { + print ''; + print ''; + if (!empty($arrayfields['timeconsumed']['checked'])) { + print ''; + print ''; + } + for ($idw = 0; $idw < 7; $idw++) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + if ($isavailable[$dayinloopfromfirstdaytoshow]['morning'] && $isavailable[$dayinloopfromfirstdaytoshow]['afternoon']) { + $currentDay = date('l', $dayinloopfromfirstdaytoshow); + $currentDay = 'workinghours_' . strtolower($currentDay); + $workinghoursWeek = $workinghoursArray->{$currentDay} * 60; + } else { + $workinghoursWeek = 0; + } + + $cssweekend = ''; + if ((($idw + 1) < $numstartworkingday) || (($idw + 1) > $numendworkingday)) { // This is a day is not inside the setup of working days, so we use a week-end css. + $cssweekend = 'weekend'; + } + + $tmpday = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + + $cssonholiday = ''; + if (!$isavailable[$tmpday]['morning'] && !$isavailable[$tmpday]['afternoon']) { + $cssonholiday .= 'onholidayallday '; + } elseif (!$isavailable[$tmpday]['morning']) { + $cssonholiday .= 'onholidaymorning '; + } elseif (!$isavailable[$tmpday]['afternoon']) { + $cssonholiday .= 'onholidayafternoon '; + } + print ''; + } + print ''; + print ''; +} + + + +// By default, we can edit only tasks we are assigned to +$restrictviewformytask = ((!isset($conf->global->PROJECT_TIME_SHOW_TASK_NOT_ASSIGNED)) ? 2 : $conf->global->PROJECT_TIME_SHOW_TASK_NOT_ASSIGNED); +if (count($tasksarray) > 0) { + //var_dump($tasksarray); // contains only selected tasks + //var_dump($tasksarraywithoutfilter); // contains all tasks (if there is a filter, not defined if no filter) + //var_dump($tasksrole); + + $j = 0; + $level = 0; + $totalforvisibletasks = projectLinesPerWeekDoliSIRH($j, $firstdaytoshow, $usertoprocess, 0, $tasksarray, $level, $projectsrole, $tasksrole, $mine, $restrictviewformytask, $isavailable, 0, $arrayfields, $extrafields); + //var_dump($totalforvisibletasks); + + // Show total for all other tasks + + // Calculate total for all tasks + $listofdistinctprojectid = array(); // List of all distinct projects + if (is_array($tasksarraywithoutfilter) && count($tasksarraywithoutfilter)) { + foreach ($tasksarraywithoutfilter as $tmptask) { + $listofdistinctprojectid[$tmptask->fk_project] = $tmptask->fk_project; + } + } + //var_dump($listofdistinctprojectid); + $totalforeachday = array(); + foreach ($listofdistinctprojectid as $tmpprojectid) { + $projectstatic->id = $tmpprojectid; + $projectstatic->loadTimeSpent($firstdaytoshow, 0, $usertoprocess->id); // Load time spent from table projet_task_time for the project into this->weekWorkLoad and this->weekWorkLoadPerTask for all days of a week + for ($idw = 0; $idw < 7; $idw++) { + $tmpday = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + $totalforeachday[$tmpday] += $projectstatic->weekWorkLoad[$tmpday]; + } + } + + //var_dump($totalforeachday); + //var_dump($totalforvisibletasks); + + // Is there a diff between selected/filtered tasks and all tasks ? + $isdiff = 0; + if (count($totalforeachday)) { + for ($idw = 0; $idw < 7; $idw++) { + $tmpday = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + $timeonothertasks = ($totalforeachday[$tmpday] - $totalforvisibletasks[$tmpday]); + if ($timeonothertasks) { + $isdiff = 1; + break; + } + } + } + + // There is a diff between total shown on screen and total spent by user, so we add a line with all other cumulated time of user + if ($isdiff) { + print ''; + print ''; + if (!empty($arrayfields['timeconsumed']['checked'])) { + print ''; + print ''; + } + for ($idw = 0; $idw < 7; $idw++) { + $cssweekend = ''; + if ((($idw + 1) < $numstartworkingday) || (($idw + 1) > $numendworkingday)) { // This is a day is not inside the setup of working days, so we use a week-end css. + $cssweekend = 'weekend'; + } + + print ''; + } + print ' '; + print ''; + } + + if ($conf->use_javascript_ajax) { + print ''; + print ''; + if (!empty($arrayfields['timeconsumed']['checked'])) { + print ''; + print ''; + } + + for ($idw = 0; $idw < $nbday; $idw++) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + if ($isavailable[$dayinloopfromfirstdaytoshow]['morning'] && $isavailable[$dayinloopfromfirstdaytoshow]['afternoon']) { + $currentDay = date('l', $dayinloopfromfirstdaytoshow); + $currentDay = 'workinghours_' . strtolower($currentDay); + $workinghoursWeek = $workinghoursArray->{$currentDay} * 60; + } else { + $workinghoursWeek = 0; + } + + $cssweekend = ''; + if ((($idw + 1) < $numstartworkingday) || (($idw + 1) > $numendworkingday)) { // This is a day is not inside the setup of working days, so we use a week-end css. + $cssweekend = 'weekend'; + } + + $tmpday = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + + $cssonholiday = ''; + if (!$isavailable[$tmpday]['morning'] && !$isavailable[$tmpday]['afternoon']) { + $cssonholiday .= 'onholidayallday '; + } elseif (!$isavailable[$tmpday]['morning']) { + $cssonholiday .= 'onholidaymorning '; + } elseif (!$isavailable[$tmpday]['afternoon']) { + $cssonholiday .= 'onholidayafternoon '; + } + + print ''; + } + if ($nbday == 7) { + print ''; + } + print ''; + + + print ''; + print ''; + if (!empty($arrayfields['timeconsumed']['checked'])) { + print ''; + print ''; + } + + for ($idw = 0; $idw < $nbday; $idw++) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + if ($isavailable[$dayinloopfromfirstdaytoshow]['morning'] && $isavailable[$dayinloopfromfirstdaytoshow]['afternoon']) { + $currentDay = date('l', $dayinloopfromfirstdaytoshow); + $currentDay = 'workinghours_' . strtolower($currentDay); + $workinghoursWeek = $workinghoursArray->{$currentDay} * 60; + } else { + $workinghoursWeek = 0; + } + + $cssweekend = ''; + if ((($idw + 1) < $numstartworkingday) || (($idw + 1) > $numendworkingday)) { // This is a day is not inside the setup of working days, so we use a week-end css. + $cssweekend = 'weekend'; + } + + $tmpday = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + + $cssonholiday = ''; + if (!$isavailable[$tmpday]['morning'] && !$isavailable[$tmpday]['afternoon']) { + $cssonholiday .= 'onholidayallday '; + } elseif (!$isavailable[$tmpday]['morning']) { + $cssonholiday .= 'onholidaymorning '; + } elseif (!$isavailable[$tmpday]['afternoon']) { + $cssonholiday .= 'onholidayafternoon '; + } + + print ''; + } + if ($nbday == 7) { + print ''; + } + print ''; + + print ''; + print ''; + if (!empty($arrayfields['timeconsumed']['checked'])) { + print ''; + print ''; + } + + for ($idw = 0; $idw < $nbday; $idw++) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + if ($isavailable[$dayinloopfromfirstdaytoshow]['morning'] && $isavailable[$dayinloopfromfirstdaytoshow]['afternoon']) { + $currentDay = date('l', $dayinloopfromfirstdaytoshow); + $currentDay = 'workinghours_' . strtolower($currentDay); + $workinghoursWeek = $workinghoursArray->{$currentDay} * 60; + } else { + $workinghoursWeek = 0; + } + $difftime = $workinghoursWeek - $totalforvisibletasks[$dayinloopfromfirstdaytoshow]; + if ($difftime < 0) { + $morecss = colorStringToArray($conf->global->DOLISIRH_EXCEEDED_TIME_SPENT_COLOR); + } else if ($difftime > 0) { + $morecss = colorStringToArray($conf->global->DOLISIRH_NOT_EXCEEDED_TIME_SPENT_COLOR); + } else if ($difftime == 0) { + $morecss = colorStringToArray($conf->global->DOLISIRH_PERFECT_TIME_SPENT_COLOR); + } + $cssweekend = ''; + if ((($idw + 1) < $numstartworkingday) || (($idw + 1) > $numendworkingday)) { // This is a day is not inside the setup of working days, so we use a week-end css. + $cssweekend = 'weekend'; + } + + $tmpday = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + + $cssonholiday = ''; + if (!$isavailable[$tmpday]['morning'] && !$isavailable[$tmpday]['afternoon']) { + $cssonholiday .= 'onholidayallday '; + } elseif (!$isavailable[$tmpday]['morning']) { + $cssonholiday .= 'onholidaymorning '; + } elseif (!$isavailable[$tmpday]['afternoon']) { + $cssonholiday .= 'onholidayafternoon '; + } + + print ''; + } + if ($nbday == 7) { + print ''; + } + print ''; + } +} else { + print ''; +} +print "
'; +$searchpicto = $form->showFilterAndCheckAddButtons(0); +print $searchpicto; +print '
'.$langs->trans("Project").''.$langs->trans("ThirdParty").''.$langs->trans("Task").''.$langs->trans("PlannedWorkload").''.$langs->trans("ProgressDeclared").''.$langs->trans("TimeSpent").'
'; + print ''; + print 'Photo'; + print ''.$langs->trans("Everybody").''; + print ''; + print '
'.$langs->trans("TimeSpent").($usertoprocess->firstname ? '
'.$usertoprocess->getNomUrl(-2).''.dol_trunc($usertoprocess->firstname, 10).'' : '').'
'; + print dol_print_date($dayinloopfromfirstdaytoshow, '%a'); + $splitted_date = preg_split('/\//', dol_print_date($dayinloopfromfirstdaytoshow, "day")); + $day = $splitted_date[0]; + $month = $splitted_date[1]; + $year = $splitted_date[2]; + print ' '; + print '
'.dol_print_date($dayinloopfromfirstdaytoshow, 'dayreduceformat').'
'; + print $langs->trans("Total"); + $lastdaytoshow = dol_time_plus_duree($firstdaytoshow, 6, 'd'); + for ($idw = 0; $idw < 7; $idw++) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + if ($isavailable[$dayinloopfromfirstdaytoshow]['morning'] && $isavailable[$dayinloopfromfirstdaytoshow]['afternoon']) { + $currentDay = date('l', $dayinloopfromfirstdaytoshow); + $currentDay = 'workinghours_' . strtolower($currentDay); + $workinghoursWeek += $workinghoursArray->{$currentDay} * 60; + } + } + print ' - '.$langs->trans("ExpectedWorkedHoursWeek", dol_print_date($firstdaytoshow, "dayreduceformat"), dol_print_date($lastdaytoshow, "dayreduceformat")).' : '.(($workinghoursWeek != 0) ? convertSecondToTime($workinghoursWeek, 'allhourmin') : '00:00').''; + print '
'.(($workinghoursWeek != 0) ? convertSecondToTime($workinghoursWeek, 'allhourmin') : '00:00').'
'; + print $langs->trans("OtherFilteredTasks"); + print ''; + $tmpday = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + $timeonothertasks = ($totalforeachday[$tmpday] - $totalforvisibletasks[$tmpday]); + if ($timeonothertasks) { + print ''; + } + print '
'; + print $langs->trans("Total"); + $CurrentDate = dol_getdate($now); + $currentWeek = getWeekNumber($CurrentDate['mday'], $CurrentDate['mon'], $CurrentDate['year']); + if ($currentWeek == $week) { + $firstDay = date( 'd', $firstdaytoshow); + $currentDay = date( 'd', $now); + $nbday = $currentDay - $firstDay + 1; + } else { + $nbday = 7; + } + + for ($idw = 0; $idw < $nbday; $idw++) { + $dayinloopfromfirstdaytoshow = dol_time_plus_duree($firstdaytoshow, $idw, 'd'); + if ($isavailable[$dayinloopfromfirstdaytoshow]['morning'] && $isavailable[$dayinloopfromfirstdaytoshow]['afternoon']) { + $currentDay = date('l', $dayinloopfromfirstdaytoshow); + $currentDay = 'workinghours_' . strtolower($currentDay); + $workinghoursWeek += $workinghoursArray->{$currentDay} * 60; + } + } + $totalspenttime = $workinghoursWeek/60/60; + print ' - '.$langs->trans("SpentWorkedHoursMonth", dol_print_date($firstdaytoshow, "dayreduceformat"), (($nbday == 7) ? dol_print_date($lastdaytoshow, "dayreduceformat") : dol_print_date($now, "dayreduceformat"))).' : '.(($workinghoursWeek != 0) ? convertSecondToTime($workinghoursWeek, 'allhourmin') : '00:00').''; + print '
'.(($workinghoursWeek != 0) ? convertSecondToTime($workinghoursWeek, 'allhourmin') : '00:00').'
'; + print $langs->trans("Total"); + + foreach ($totalforvisibletasks as $task) { + $totalconsumedtime += $task; + } + print ' - '.$langs->trans("ConsumedWorkedHoursMonth", dol_print_date($firstdaytoshow, "dayreduceformat"), (($nbday == 7) ? dol_print_date($lastdaytoshow, "dayreduceformat") : dol_print_date($now, "dayreduceformat"))).' : '.convertSecondToTime($totalconsumedtime, 'allhourmin').''; + print ''.convertSecondToTime($totalconsumedtime, 'allhourmin').'
'.dol_print_date($workinghoursWeek, 'hour').'
'; + print $langs->trans("Total"); + $difftotaltime = $totalspenttime * 60 * 60 - $totalconsumedtime; + if ($difftotaltime < 0) { + $morecss = colorStringToArray($conf->global->DOLISIRH_EXCEEDED_TIME_SPENT_COLOR); + } else if ($difftotaltime > 0) { + $morecss = colorStringToArray($conf->global->DOLISIRH_NOT_EXCEEDED_TIME_SPENT_COLOR); + } else if ($difftotaltime == 0) { + $morecss = colorStringToArray($conf->global->DOLISIRH_PERFECT_TIME_SPENT_COLOR); + } + print ' - '.$langs->trans("DiffSpentAndConsumedWorkedHoursMonth", dol_print_date($firstdaytoshow, "dayreduceformat"), (($nbday == 7) ? dol_print_date($lastdaytoshow, "dayreduceformat") : dol_print_date($now, "dayreduceformat"))).' : '.(($difftotaltime != 0) ? convertSecondToTime(abs($difftotaltime), 'allhourmin') : '00:00').''; + print ''.(($difftotaltime != 0) ? convertSecondToTime(abs($difftotaltime), 'allhourmin') : '00:00').'
'.(($difftime != 0) ? convertSecondToTime(abs($difftime), 'allhourmin') : '00:00').'
'.$langs->trans("NoAssignedTasks").'
"; +print '
'; + +print ''."\n"; + +print $form->buttonsSaveCancel("Save", ''); + +print '
'."\n\n"; + +$modeinput = 'hours'; + +if ($conf->use_javascript_ajax) { + print "\n\n"; + print ''; +} + +// End of page +llxFooter(); +$db->close(); diff --git a/view/workinghours_card.php b/view/workinghours_card.php new file mode 100644 index 0000000..1282a4a --- /dev/null +++ b/view/workinghours_card.php @@ -0,0 +1,264 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file view/workinghours_card.php + * \ingroup dolisirh + * \brief Page to view Working Hours + */ + +// Load Dolibarr environment +$res = 0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if ( ! $res && ! empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"] . "/main.inc.php"; +// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME +$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1; +while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) { $i--; $j--; } +if ( ! $res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1)) . "/main.inc.php")) $res = @include substr($tmp, 0, ($i + 1)) . "/main.inc.php"; +if ( ! $res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1))) . "/main.inc.php")) $res = @include dirname(substr($tmp, 0, ($i + 1))) . "/main.inc.php"; +// Try main.inc.php using relative path +if ( ! $res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php"; +if ( ! $res && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php"; +if ( ! $res) die("Include of main fails"); + +// Libraries +require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php'; +require_once DOL_DOCUMENT_ROOT . '/core/lib/usergroups.lib.php'; +require_once DOL_DOCUMENT_ROOT . '/core/lib/images.lib.php'; + +require_once './../class/workinghours.class.php'; + +// Global variables definitions +global $db, $hookmanager, $langs, $user; + +// Load translation files required by the page +$langs->loadLangs(array("dolisirh@dolisirh")); + +// Parameters +$action = (GETPOST('action', 'aZ09') ? GETPOST('action', 'aZ09') : 'view'); + +$socid = GETPOST('socid', 'int') ? GETPOST('socid', 'int') : GETPOST('id', 'int'); +if ($usertmp->socid) $socid = $usertmp->socid; +if (empty($socid) && $action == 'view') $action = 'create'; + +$usertmp = new User($db); + +// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context +$hookmanager->initHooks(array('userworkinghours', 'globalcard')); + +if ($action == 'view' && $usertmp->fetch($socid) <= 0) { + $langs->load("errors"); + print($langs->trans('ErrorRecordNotFound')); + exit; +} + +// Security check +$permissiontoadd = $usertmp->rights->societe->creer; + +/* + * Actions + */ + +$parameters = array(); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $usertmp, $action); // Note that $action and $usertmp may have been modified by some hooks +if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + +if (($action == 'update' && ! GETPOST("cancel", 'alpha')) || ($action == 'updateedit')) { + $object = new Workinghours($db); + $object->element_type = $usertmp->element; + $object->element_id = GETPOST('id'); + $object->status = 1; + $object->fk_user_creat = $user->id; + $object->schedule_monday = GETPOST('schedule_monday', 'string'); + $object->schedule_tuesday = GETPOST('schedule_tuesday', 'string'); + $object->schedule_wednesday = GETPOST('schedule_wednesday', 'string'); + $object->schedule_thursday = GETPOST('schedule_thursday', 'string'); + $object->schedule_friday = GETPOST('schedule_friday', 'string'); + $object->schedule_saturday = GETPOST('schedule_saturday', 'string'); + $object->schedule_sunday = GETPOST('schedule_sunday', 'string'); + + $object->workinghours_monday = GETPOST('workinghours_monday', 'integer'); + $object->workinghours_tuesday = GETPOST('workinghours_tuesday', 'integer'); + $object->workinghours_wednesday = GETPOST('workinghours_wednesday', 'integer'); + $object->workinghours_thursday = GETPOST('workinghours_thursday', 'integer'); + $object->workinghours_friday = GETPOST('workinghours_friday', 'integer'); + $object->workinghours_saturday = GETPOST('workinghours_saturday', 'integer'); + $object->workinghours_sunday = GETPOST('workinghours_sunday', 'integer'); + $result = $object->create($usertmp); + if ($result > 0) { + setEventMessages($langs->trans('UserWorkingHoursSaved'), null, 'mesgs'); + } else { + setEventMessages($langs->trans('UserWorkingHoursSave'), null, 'error'); + } +} + +/* + * View + */ + +$object = new Workinghours($db); + +$morewhere = ' AND element_id = ' . GETPOST('id'); +$morewhere .= ' AND element_type = ' . "'" . $usertmp->element . "'"; +$morewhere .= ' AND status = 1'; + +$object->fetch(0, '', $morewhere); + +if ($socid > 0 && empty($usertmp->id)) { + $result = $usertmp->fetch($socid); + if ($result <= 0) dol_print_error('', $usertmp->error); +} + +$title = $langs->trans("User"); +if ( ! empty($conf->global->MAIN_HTML_TITLE) && preg_match('/thirdpartynameonly/', $conf->global->MAIN_HTML_TITLE) && $usertmp->name) $title = $usertmp->name . " - " . $langs->trans('WorkingHours'); +$help_url = 'EN:Module_Third_Parties|FR:Module_DigiriskDolibarr#L.27onglet_Horaire_de_travail|ES:Empresas'; + +$morecss = array("/dolisirh/css/dolisirh.css"); + +llxHeader('', $title, $help_url, '', '', '', array(), $morecss); + +if ( ! empty($usertmp->id)) $res = $usertmp->fetch_optionals(); + +// Object card +// ------------------------------------------------------------ +$morehtmlref = '
'; +$morehtmlref .= '
'; +$head = user_prepare_head($usertmp); +print dol_get_fiche_head($head, 'workinghours', $langs->trans("User"), 0, 'company'); +$linkback = '' . $langs->trans("BackToList") . ''; +dol_banner_tab($usertmp, 'socid', $linkback, ($usertmp->socid ? 0 : 1), 'rowid', 'nom'); + +print dol_get_fiche_end(); + +print load_fiche_titre($langs->trans("UserWorkingHours"), '', ''); + +//Show common fields + +if ( ! is_object($form)) $form = new Form($db); + +print '
'; +print ''; +print ''; +print ''; + +print ''; + +print '' . "\n"; + +print ''; + +print ''; +print '' . "\n"; + +print ''; +print ''; +print '' . "\n"; + +print ''; +print ''; +print '' . "\n"; + +print ''; +print ''; +print '' . "\n"; + +print ''; +print ''; +print '' . "\n"; + +print ''; +print ''; +print '' . "\n"; + +print ''; +print ''; +print '' . "\n"; + +print '
' . $langs->trans("Day") . '' . $langs->trans("Schedule") . ''. $langs->trans('WorkingHours(min)') .'
'; +print $form->textwithpicto($langs->trans("Monday"), ''); +print ''; +print 'global->MAIN_OPTIMIZEFORTEXTBROWSER) ? '' : ' autofocus="autofocus"') . '>'; +print $form->textwithpicto('', $langs->trans("OpeningHoursFormatDesc")); +print ''; +print 'global->MAIN_OPTIMIZEFORTEXTBROWSER) ? '' : ' autofocus="autofocus"') . '>'; +print $form->textwithpicto('', $langs->trans("WorkingHoursFormatDesc")); +print '
'; +print $form->textwithpicto($langs->trans("Tuesday"),''); +print ''; +print 'global->MAIN_OPTIMIZEFORTEXTBROWSER) ? '' : ' autofocus="autofocus"') . '>'; +print $form->textwithpicto('', $langs->trans("OpeningHoursFormatDesc")); +print ''; +print 'global->MAIN_OPTIMIZEFORTEXTBROWSER) ? '' : ' autofocus="autofocus"') . '>'; +print $form->textwithpicto('', $langs->trans("WorkingHoursFormatDesc")); +print '
'; +print $form->textwithpicto($langs->trans("Wednesday"),''); +print ''; +print 'global->MAIN_OPTIMIZEFORTEXTBROWSER) ? '' : ' autofocus="autofocus"') . '>'; +print $form->textwithpicto('', $langs->trans("OpeningHoursFormatDesc")); +print ''; +print 'global->MAIN_OPTIMIZEFORTEXTBROWSER) ? '' : ' autofocus="autofocus"') . '>'; +print $form->textwithpicto('', $langs->trans("WorkingHoursFormatDesc")); +print '
'; +print $form->textwithpicto($langs->trans("Thursday"),''); +print ''; +print 'global->MAIN_OPTIMIZEFORTEXTBROWSER) ? '' : ' autofocus="autofocus"') . '>'; +print $form->textwithpicto('', $langs->trans("OpeningHoursFormatDesc")); +print ''; +print 'global->MAIN_OPTIMIZEFORTEXTBROWSER) ? '' : ' autofocus="autofocus"') . '>'; +print $form->textwithpicto('', $langs->trans("WorkingHoursFormatDesc")); +print '
'; +print $form->textwithpicto($langs->trans("Friday"), ''); +print ''; +print 'global->MAIN_OPTIMIZEFORTEXTBROWSER) ? '' : ' autofocus="autofocus"') . '>'; +print $form->textwithpicto('', $langs->trans("OpeningHoursFormatDesc")); +print ''; +print 'global->MAIN_OPTIMIZEFORTEXTBROWSER) ? '' : ' autofocus="autofocus"') . '>'; +print $form->textwithpicto('', $langs->trans("WorkingHoursFormatDesc")); +print '
'; +print $form->textwithpicto($langs->trans("Saturday"), ''); +print ''; +print 'global->MAIN_OPTIMIZEFORTEXTBROWSER) ? '' : ' autofocus="autofocus"') . '>'; +print $form->textwithpicto('', $langs->trans("OpeningHoursFormatDesc")); +print ''; +print 'global->MAIN_OPTIMIZEFORTEXTBROWSER) ? '' : ' autofocus="autofocus"') . '>'; +print $form->textwithpicto('', $langs->trans("WorkingHoursFormatDesc")); +print '
'; +print $form->textwithpicto($langs->trans("Sunday"),''); +print ''; +print 'global->MAIN_OPTIMIZEFORTEXTBROWSER) ? '' : ' autofocus="autofocus"') . '>'; +print $form->textwithpicto('', $langs->trans("OpeningHoursFormatDesc")); +print ''; +print 'global->MAIN_OPTIMIZEFORTEXTBROWSER) ? '' : ' autofocus="autofocus"') . '>'; +print $form->textwithpicto('', $langs->trans("WorkingHoursFormatDesc")); +print '
'; + +if ($firepermit) { + $status = $firepermit->status; +} elseif ($preventionplan) { + $status = $preventionplan->status; +} + +print '
'; +print ''; +print '
'; +print '
'; + +print '
'; + +// End of page +llxFooter(); +$db->close();