From 3a48af0963983c9aef8aea7b950c7133ce5c0465 Mon Sep 17 00:00:00 2001 From: Aniketk9211 <71625396+Aniketk9211@users.noreply.github.com> Date: Thu, 18 Apr 2024 01:01:42 +0530 Subject: [PATCH] Add files --- LICENSE.md | 596 ++++++++++++++++++++++++++++++++++ README.md | 44 +++ amd/src/commands.js | 71 ++++ amd/src/common.js | 32 ++ amd/src/configuration.js | 57 ++++ amd/src/plugin.js | 53 +++ amd/src/ui.js | 160 +++++++++ chem/app.js | 133 ++++++++ chem/chem.css | 29 ++ chem/chem.html | 140 ++++++++ classes/plugininfo.php | 45 +++ db/install.php | 32 ++ db/uninstall.php | 32 ++ lang/en/tiny_chemdraw.php | 32 ++ pix/icon.png | Bin 0 -> 11548 bytes pix/noun-chemical-1892838.png | Bin 0 -> 31441 bytes pix/noun-chemical-1892838.svg | 1 + settings.php | 35 ++ templates/moldraw.mustache | 65 ++++ version.php | 31 ++ 20 files changed, 1588 insertions(+) create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 amd/src/commands.js create mode 100644 amd/src/common.js create mode 100644 amd/src/configuration.js create mode 100644 amd/src/plugin.js create mode 100644 amd/src/ui.js create mode 100644 chem/app.js create mode 100644 chem/chem.css create mode 100644 chem/chem.html create mode 100644 classes/plugininfo.php create mode 100644 db/install.php create mode 100644 db/uninstall.php create mode 100644 lang/en/tiny_chemdraw.php create mode 100644 pix/icon.png create mode 100644 pix/noun-chemical-1892838.png create mode 100644 pix/noun-chemical-1892838.svg create mode 100644 settings.php create mode 100644 templates/moldraw.mustache create mode 100644 version.php diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..16d89e0 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,596 @@ +GNU GENERAL PUBLIC LICENSE +========================== + +Version 3, 29 June 2007 + +Copyright © 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 +<>. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..c1ca97d --- /dev/null +++ b/README.md @@ -0,0 +1,44 @@ +# Chem Drawing Tool # + +TODO Describe the plugin shortly here. + +TODO Provide more detailed description here. + +## Installing via uploaded ZIP file ## + +1. Log in to your Moodle site as an admin and go to _Site administration > + Plugins > Install plugins_. +2. Upload the ZIP file with the plugin code. You should only be prompted to add + extra details if your plugin type is not automatically detected. +3. Check the plugin validation report and finish the installation. + +## Installing manually ## + +The plugin can be also installed by putting the contents of this directory to + + {your/moodle/dirroot}/lib/editor/tiny/plugins/chemdraw + +Afterwards, log in to your Moodle site as an admin and go to _Site administration > +Notifications_ to complete the installation. + +Alternatively, you can run + + $ php admin/cli/upgrade.php + +to complete the installation from the command line. + +## License ## + +2024 Aniket Kumar + +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 . diff --git a/amd/src/commands.js b/amd/src/commands.js new file mode 100644 index 0000000..f7ddeb7 --- /dev/null +++ b/amd/src/commands.js @@ -0,0 +1,71 @@ +// This file is part of Moodle - https://moodle.org/ +// +// Moodle 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. +// +// Moodle 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 Moodle. If not, see . + +/** + * Commands helper for the Moodle tiny_chemdraw plugin. + * + * @module plugintype_pluginname/commands + * @copyright 2024 Aniket Kumar + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import {getButtonImage} from "editor_tiny/utils"; +import {get_string as getString} from "core/str"; +import {handleAction} from "./ui"; +import {component, startMolDrawButtonName, startMolDrawMenuItemName, icon} from "./common"; + +/** + * Handle the action for your plugin. + * @param {TinyMCE.editor} editor The tinyMCE editor instance. + */ +// handle Action funciton.. + + +/** + * Get the setup function for the buttons. + * + * This is performed in an async function which ultimately returns the registration function as the + * Tiny.AddOnManager.Add() function does not support async functions. + * + * @returns {function} The registration function to call within the Plugin.add function. + */ +export const getSetup = async() => { + try { + const [startMolDrawButtonNameTitle, startMolDrawMenuItemNameTitle, buttonImage] = await Promise.all([ + getString("button_startMolDraw", component), + getString("menuitem_startMolDraw", component), + getButtonImage("icon", component), + ]); + + return (editor) => { + editor.ui.registry.addIcon(icon, buttonImage.html); + + editor.ui.registry.addButton(startMolDrawButtonName, { + icon, + tooltip: startMolDrawButtonNameTitle, + onAction: () => handleAction(editor), + }); + + editor.ui.registry.addMenuItem(startMolDrawMenuItemName, { + icon, + text: startMolDrawMenuItemNameTitle, + onAction: () => handleAction(editor), + }); + }; + } catch (error) { + // eslint-disable-next-line no-alert + alert("Error setting up plugin:", error); + } + }; diff --git a/amd/src/common.js b/amd/src/common.js new file mode 100644 index 0000000..a4742cd --- /dev/null +++ b/amd/src/common.js @@ -0,0 +1,32 @@ +// This file is part of Moodle - https://moodle.org/ +// +// Moodle 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. +// +// Moodle 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 Moodle. If not, see . + +/** + * Common values helper for the Moodle tiny_chemdraw plugin. + * + * @module plugintype_pluginname/common + * @copyright 2024 Aniket Kumar + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +const component = 'tiny_moldraw'; + +export default { + component, + pluginName: `${component}/plugin`, + icon: component, + startMolDrawButtonName: `${component}_startMolDraw`, + startMolDrawMenuItemName: `${component}_startMolDraw`, +}; diff --git a/amd/src/configuration.js b/amd/src/configuration.js new file mode 100644 index 0000000..5ba0c71 --- /dev/null +++ b/amd/src/configuration.js @@ -0,0 +1,57 @@ +// This file is part of Moodle - https://moodle.org/ +// +// Moodle 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. +// +// Moodle 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 Moodle. If not, see . + +/** + * Tiny tiny_chemdraw for Moodle. + * + * @module plugintype_pluginname/plugin + * @copyright 2024 Aniket Kumar + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import { + startMolDrawButtonName, + startMolDrawMenuItemName, +} from './common'; + +import { + addMenubarItem, + addToolbarButtons, +} from 'editor_tiny/utils'; + +const getToolbarConfiguration = (instanceConfig) => { + let toolbar = instanceConfig.toolbar; + toolbar = addToolbarButtons(toolbar, 'content', [ + startMolDrawButtonName, + ]); + + return toolbar; +}; + +const getMenuConfiguration = (instanceConfig) => { + let menu = instanceConfig.menu; + menu = addMenubarItem(menu, 'file', [ + startMolDrawMenuItemName, + ].join(' ')); + + return menu; +}; + +export const configure = (instanceConfig) => { + return { + toolbar: getToolbarConfiguration(instanceConfig), + menu: getMenuConfiguration(instanceConfig), + }; +}; diff --git a/amd/src/plugin.js b/amd/src/plugin.js new file mode 100644 index 0000000..bc3c56d --- /dev/null +++ b/amd/src/plugin.js @@ -0,0 +1,53 @@ +// This file is part of Moodle - https://moodle.org/ +// +// Moodle 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. +// +// Moodle 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 Moodle. If not, see . + +/** + * Tiny tiny_chemdraw for Moodle. + * + * @module plugintype_pluginname/plugin + * @copyright 2024 Aniket Kumar + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +import { getTinyMCE } from 'editor_tiny/loader'; +import { getPluginMetadata } from 'editor_tiny/utils'; + +import { component, pluginName } from './common'; +import { register as registerOptions } from './options'; +import { getSetup as getCommandSetup } from './commands'; +import * as Configuration from './configuration'; + +// Setup the tiny_moldraw Plugin. +export default new Promise((resolve) => { + Promise.all([ + getTinyMCE(), + getPluginMetadata(component, pluginName), + getCommandSetup(), + ]).then(([tinyMCE, pluginMetadata, setupCommands]) => { + // Register the plugin with TinyMCE + tinyMCE.PluginManager.add(pluginName, (editor) => { + // Register any options that your plugin has + registerOptions(editor); + + // Setup any commands such as buttons, menu items, and so on. + setupCommands(editor); + + // Return the pluginMetadata object. This is used by TinyMCE to display a help link for your plugin. + return pluginMetadata; + }); + + resolve([pluginName, Configuration]); + }); +}); \ No newline at end of file diff --git a/amd/src/ui.js b/amd/src/ui.js new file mode 100644 index 0000000..f14a6b9 --- /dev/null +++ b/amd/src/ui.js @@ -0,0 +1,160 @@ +import Modal from "core/modal"; +import Templates from "core/templates"; + +class MyModal extends Modal { + static TYPE = "tiny_moldraw/moldraw"; + static TEMPLATE = "tiny_moldraw/moldraw"; + configure(modalConfig) { + // Show this modal on instantiation. + modalConfig.show = true; + // Remove from the DOM on close. + modalConfig.removeOnClose = true; + } +} + +export const handleAction = async () => { + await MyModal.create(); +}; + +/** + * @param {*} url + * @param { }type + */ +async function loadResource(url, type) { + return new Promise((resolve, reject) => { + if (type === "script") { + var script = document.createElement("script"); + script.type = "text/javascript"; + script.onload = resolve; + script.onerror = reject; + script.src = url; + document.getElementsByTagName("body")[0].appendChild(script); + } else if (type === "stylesheet") { + var link = document.createElement("link"); + link.rel = "stylesheet"; + link.type = "text/css"; + link.onload = resolve; + link.onerror = reject; + link.href = url; + document.getElementsByTagName("head")[0].appendChild(link); + } else { + reject(new Error("Invalid resource type")); + } + }); +} + +/** + * + */ +async function loadAndRunAnotherFunction() { + try { + await loadResource("../../ChemDoodle/install/ChemDoodleWeb.css", "stylesheet"); + await loadResource("../../ChemDoodle/install/uis/jquery-ui-1.11.4.css", "stylesheet"); + await loadResource("../../ChemDoodle/install/ChemDoodleWeb.js", "script"); + await loadResource("../../ChemDoodle/install/uis/ChemDoodleWeb-uis.js", "script"); + await loadResource("../../chem/chem.css", "stylesheet"); + + // All resources are loaded, now you can execute your code + // For example, you can run the provided script here + + ChemDoodle.ELEMENT["H"].jmolColor = "black"; + ChemDoodle.ELEMENT["S"].jmolColor = "#B9A130"; + // Main ketcher. + const sketcher = new ChemDoodle.SketcherCanvas("sketcher", 600, 350, { + useServices: false, + requireStartingAtom: false, + }); + // We init the ketcher with an empty molecule object. + sketcher.styles.atoms_displayTerminalCarbonLabels_2D = true; + sketcher.styles.atoms_useJMOLColors = true; + sketcher.styles.bonds_clearOverlaps_2D = true; + sketcher.styles.shapes_color = "#c10000"; + sketcher.repaint(); + + // Preview ketcher. + const sketcherViewer = new ChemDoodle.ViewerCanvas( + "sketcher-viewer-atto", + 100, + 100 + ); + sketcherViewer.styles.atoms_displayTerminalCarbonLabels_2D = true; + sketcherViewer.styles.atoms_useJMOLColors = true; + sketcherViewer.styles.bonds_clearOverlaps_2D = true; + + sketcherViewer.emptyMessage = "No data loaded"; + sketcher.oldFunc = sketcher.checksOnAction; + + /* Refactor the function, in order for the preview ketcher to be a copy of the main ketcher, + updated at every modification of the main ketcher. */ + sketcher.checksOnAction = function (force) { + this.oldFunc(force); + let mols = sketcher.molecules; + let forms = sketcher.shapes; + sketcherViewer.loadContent(mols, forms); + sketcher.center(); + for (let i = 0, ii = this.molecules.length; i < ii; i++) { + this.molecules[i].check(); + } + } + + // eslint - disable - next - line no - console + console.log("All resources loaded successfully."); + } catch { + console.log("error"); + } +} +// Call the function to load all resources and run the provided script + + + +function function_resize() { + let input_width = document.getElementById('width_input_molstructure').valueAsNumber; + let input_height = document.getElementById('height_input_molstructure').valueAsNumber; + let width; + let height; + + if (input_width > 0) { + width = input_width; + } else { + width = 100; + } + if (input_height > 0) { + height = input_height; + } else { + height = 100; + } + sketcherViewer.resize(width, height); +} + +function insert() { + if (window.parent.tinyMCE && window.parent.tinyMCE.activeEditor) { + let mol = sketcherViewer.getMolecule(); + let src = ChemDoodle.io.png.string(sketcherViewer); + let molFile = ChemDoodle.writeMOL(mol); + let width = document.getElementById('width_input_molstructure').valueAsNumber; + let height = document.getElementById('height_input_molstructure').valueAsNumber; + var content = + ''; + + window.parent.tinyMCE.activeEditor.execCommand( + "mceInsertContent", + 0, + content + ); + window.parent.tinyMCE.activeEditor.execCommand( + "mceInsertContent", + 0, + "" + ); + var modal = window.parent.document.querySelector('.modal'); + var closeButton = modal.querySelector('.close'); + closeButton.click(); + } + console.log("button Click") +} diff --git a/chem/app.js b/chem/app.js new file mode 100644 index 0000000..3be5ff0 --- /dev/null +++ b/chem/app.js @@ -0,0 +1,133 @@ +async function loadResource(url, type) { + return new Promise((resolve, reject) => { + if (type === 'script') { + var script = document.createElement("script"); + script.type = "text/javascript"; + script.onload = resolve; + script.onerror = reject; + script.src = url; + document.getElementsByTagName("head")[0].appendChild(script); + } else if (type === 'stylesheet') { + var link = document.createElement("link"); + link.rel = "stylesheet"; + link.type = "text/css"; + link.onload = resolve; + link.onerror = reject; + link.href = url; + document.getElementsByTagName("head")[0].appendChild(link); + } else { + reject(new Error('Invalid resource type')); + } + }); +} + +async function loadAndRunAnotherFunction() { + try { + await Promise.all([ + loadResource("../../ChemDoodle/install/ChemDoodleWeb.css", 'stylesheet'), + loadResource("../../ChemDoodle/install/uis/jquery-ui-1.11.4.css", 'stylesheet'), + loadResource("../../ChemDoodle/install/ChemDoodleWeb.js", 'script'), + loadResource("../../ChemDoodle/install/uis/ChemDoodleWeb-uis.js", 'script'), + loadResource("../../chem/chem.css", 'stylesheet') + ]); + + // All resources are loaded, now you can execute your code + // For example, you can run the provided script here + + ChemDoodle.ELEMENT['H'].jmolColor = 'black'; + ChemDoodle.ELEMENT['S'].jmolColor = '#B9A130'; + // Main ketcher. + const sketcher = new ChemDoodle.SketcherCanvas('sketcher', 600, 350, { useServices: false, requireStartingAtom: false }); + // We init the ketcher with an empty molecule object. + sketcher.styles.atoms_displayTerminalCarbonLabels_2D = true; + sketcher.styles.atoms_useJMOLColors = true; + sketcher.styles.bonds_clearOverlaps_2D = true; + sketcher.styles.shapes_color = "#c10000"; + sketcher.repaint(); + + + // Preview ketcher. + const sketcher_viewer = new ChemDoodle.ViewerCanvas('sketcher-viewer-atto', 100, 100); + sketcher_viewer.styles.atoms_displayTerminalCarbonLabels_2D = true; + sketcher_viewer.styles.atoms_useJMOLColors = true; + sketcher_viewer.styles.bonds_clearOverlaps_2D = true; + //sketcher_viewer.repaint(); + sketcher_viewer.emptyMessage = 'No data loaded'; + sketcher.oldFunc = sketcher.checksOnAction; + + /* Refactor the function, in order for the preview ketcher to be a copy of the main ketcher, + updated at every modification of the main ketcher. */ + sketcher.checksOnAction = function (force) { + this.oldFunc(force); + //sketcher.repaint(); + let mols = sketcher.molecules; + let forms = sketcher.shapes; + sketcher_viewer.loadContent(mols, forms); + sketcher.center(); + for (let i = 0, ii = this.molecules.length; i < ii; i++) { + this.molecules[i].check(); + } + } + + /* Button activated function, checks for the values of width and height in the input elements. + If empty, uses the default value. */ + function function_resize() { + let input_width = document.getElementById('width_input_molstructure').valueAsNumber; + let input_height = document.getElementById('height_input_molstructure').valueAsNumber; + let width; + let height; + + if (input_width > 0) { + width = input_width; + } else { + width = 100; + } + if (input_height > 0) { + // console.log('inif'); + height = input_height; + } else { + // console.log('inelse'); + height = 100; + } + sketcher_viewer.resize(width, height); + } + function insert() { + if (window.parent.tinyMCE && window.parent.tinyMCE.activeEditor) { + let mol = sketcher_viewer.getMolecule(); + let src = ChemDoodle.io.png.string(sketcher_viewer); + let molFile = ChemDoodle.writeMOL(mol); + let width = document.getElementById('width_input_molstructure').valueAsNumber; + let height = document.getElementById('height_input_molstructure').valueAsNumber; + var content = + ''; + + window.parent.tinyMCE.activeEditor.execCommand( + "mceInsertContent", + 0, + content + ); + window.parent.tinyMCE.activeEditor.execCommand( + "mceInsertContent", + 0, + "" + ); + var modal = window.parent.document.querySelector('.modal'); + var closeButton = modal.querySelector('.close'); + closeButton.click(); + } + console.log("button Click") + } + console.log("All resources loaded successfully."); + } catch (error) { + console.error("Error loading resources:", error); + } +} + +// Call the function to load all resources and run the provided script +loadAndRunAnotherFunction(); diff --git a/chem/chem.css b/chem/chem.css new file mode 100644 index 0000000..5d91a26 --- /dev/null +++ b/chem/chem.css @@ -0,0 +1,29 @@ +body { + margin: 0; + padding: 0; + overflow-x: hidden; /* Hide horizontal scrollbar */ +} +#actionbutton { + position: fixed; + bottom: 20px; + right: 20px; + padding: 10px 20px; + font-size: 16px; + font-weight: bold; + text-transform: uppercase; + color: #fff; + background-color: #4CAF50; + border: none; + border-radius: 5px; + cursor: pointer; + transition: background-color 0.3s ease; +} + +#actionbutton:hover { + background-color: #45a049; +} + +#container { + width: 100%; + padding-bottom: 60px; +} \ No newline at end of file diff --git a/chem/chem.html b/chem/chem.html new file mode 100644 index 0000000..74f4622 --- /dev/null +++ b/chem/chem.html @@ -0,0 +1,140 @@ + + + + + + ChemDoodle Web Component Sketcher (Full Sketcher) + + + + + + + + +
+ +
+

+
+ +
+
+ + +

+
+ +
+ +

+
+ +
+ +
+

+
+ + +
+ +
+ +
+ + + + + \ No newline at end of file diff --git a/classes/plugininfo.php b/classes/plugininfo.php new file mode 100644 index 0000000..a57859d --- /dev/null +++ b/classes/plugininfo.php @@ -0,0 +1,45 @@ +. + +/** + * Tiny Chem Drawing Tool plugin for Moodle. + * + * @package tiny_chemdraw + * @copyright 2024 Aniket Kumar + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace tiny_chemdraw; + +use context; +use editor_tiny\plugin; +use editor_tiny\plugin_with_buttons; +use editor_tiny\plugin_with_menuitems; + +class plugininfo extends plugin implements plugin_with_buttons, plugin_with_menuitems { + + public static function get_available_buttons(): array { + return [ + 'tiny_chemdraw/plugin', + ]; + } + + public static function get_available_menuitems(): array { + return [ + 'tiny_chemdraw/plugin', + ]; + } +} diff --git a/db/install.php b/db/install.php new file mode 100644 index 0000000..a21b6c1 --- /dev/null +++ b/db/install.php @@ -0,0 +1,32 @@ +. + +/** + * Code to be executed after the plugin's database scheme has been installed is defined here. + * + * @package tiny_chemdraw + * @category upgrade + * @copyright 2024 Aniket Kumar + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * Custom code to be run on installing the plugin. + */ +function xmldb_tiny_chemdraw_install() { + + return true; +} diff --git a/db/uninstall.php b/db/uninstall.php new file mode 100644 index 0000000..1630aa9 --- /dev/null +++ b/db/uninstall.php @@ -0,0 +1,32 @@ +. + +/** + * Code that is executed before the tables and data are dropped during the plugin uninstallation. + * + * @package tiny_chemdraw + * @category upgrade + * @copyright 2024 Aniket Kumar + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * Custom uninstallation procedure. + */ +function xmldb_tiny_chemdraw_uninstall() { + + return true; +} diff --git a/lang/en/tiny_chemdraw.php b/lang/en/tiny_chemdraw.php new file mode 100644 index 0000000..0c6899b --- /dev/null +++ b/lang/en/tiny_chemdraw.php @@ -0,0 +1,32 @@ +. + +/** + * Plugin strings are defined here. + * + * @package tiny_chemdraw + * @category string + * @copyright 2024 Aniket Kumar + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$string['pluginname'] = 'Chemical Structure Drawing Tool'; +$string['button_startMolDraw'] = 'Start MOL Draw'; +$string['menuitem_startMolDraw'] = 'Start MOL Draw'; +$string['privacy:metadata'] = 'Chemical Structure Editor does not store any personal data'; +$string['sketchtitle'] = 'Chemical Structure Editor'; diff --git a/pix/icon.png b/pix/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..996aa9878633ed8e12557fbb8c44f08c0bb17ec2 GIT binary patch literal 11548 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 E2TJAPdH?_b literal 0 HcmV?d00001 diff --git a/pix/noun-chemical-1892838.png b/pix/noun-chemical-1892838.png new file mode 100644 index 0000000000000000000000000000000000000000..2f9e4fbd446982470218ccf76967a2b221bd3bfc GIT binary patch literal 31441 zcmdpdg;!KxwD1fmEiJ7hh=d?Yr^?U*0!j-**U;TykTOW4lyt+;4WpDGAw4tJIC+pW>)TMzH%Kp+qADlFwkT~d&h*7ASdE=+Qp_lerr5E{1))Mwk_3vU=ej8WPOtfbM_Vx z7Y1a&56Alu;E|XB?Gj2u18hY4^g(kUV#FALkK<^zDFax1KH`S#X0VS%=bm%$-k?u> z#t0AiqmPlwS-{dEmhs#XPRymd!g zsU_-$JERGU2~E>J!ZuLW(~B~*4XC^s{R5ADG{`caJ)kBX@hFD>1|`!JF%JK?asc-e zXCX3i_H(2r6nLK42Exd(Y`v|$m#Bm7uO>HRqvN1-&;VC^jecS(-mcD|#_b#O9^{Ho zALlUzgZy5%irsw1sl@_vre5UX_md{&H<}i>QAk`KD`?c$1iaD|#n5Lc^jLH`rX?hlWS)@AB|pQF`pV#75qT(H({_ zNW0jl6CnGC;GZXQ@rG<3UT%nY#Qq%545Bckdv@OcM!3;zkx-H@?`=A^-a{14-md%& zVY}XcC`*i#dsIJ$9=0WVng^ha;5V0n+s$rjq~|pIuzC6^aK0BV{}f?4XozZC^*7#x zFB$9>Z1W-%zdoJc0`Ek}EC~ zUB^Gg=LWNAEqc5SL{hFWp~jes%9DLE1Fm5=oTzlWp<24UCrcugLih3Ib!=l9_(0sB zJM5-2U+5&?h-lZ#60mc&v&}{oqsQHE=zkO?-N8Y<+h?{v?PZzI zXEwv!@rJqD-!dZfstEtH7}8?7`hWT!g$~O;M0euM=e0x$7w)wOG9rwsG@5SaJ6jke zM!h&~C@ui@E713@y@#6bYB>CXJrs_MCf3njvR2=xf3Jt4nUccuGJ&oKquIoBSH5coqJDTEI z({ykcVqCu|mC)a;#k?YLV**a&joPQ~f<4}r!4RIV{n%ujdh^=NQp?-$!AR*m!qOl; zn%CC*n^92AshZkuyi?PS^nFHIy94;=c#nnW-Q4Yj>r0G}uI%t+36hl?jBj+mdeqHu zC*lvZxMsF#qHic+!APg#&5hj)G2UMEwa4rERv4C~Pm7DdT}}|NX1bN%AoZN3OtTPa zUO8ew!khCM`g>3wnA2I0sHW`SPZ^?u0{pOqO5oc zc$!i2UAz48br9y%jP{_jmW&?YqxPNtAoYNaP0V;He+oNFzH5K#{g}Y(n}zt4#Y~%n{c6miC5GSj){HB=&rK<1Bw(}nI0>q#*uAEhD*-a?x zVm+S4dtP#4;MoF`d_bn3FOu;JsAowe9~|@MD;y=dSHf1JZXo82Rp7*%Jx6MZy8l3e z)GfoBFWXda6l-mCdlt(?MXuVWYJj#!|6tcT4=XJQO`$5NaLJ;?evrHma4- z%woNpSNU!{t{G`c$k;VbBO=f~jkhst*8k9AaKI;v*cu;DlxM2uceCy6we^z(L{jBEK2bbmby@LB= zx8Q$XWpS?D#suBD9Lbgiknt2{MC^1K?*hYxV4uWP3o8Mn`9Chepp~g*6kZZrKY5JK zmQ|UYL5~ho_YUN5rEmj0E6|=DUuIJtt4I!Uucv;Y`sDUMEUc=SOA2V_N_Zc_AD?`X z#h{x8{)bA$+X(;WQmTo+`{!M(Qimbbl*fQuQwB>bz6@Vuj>T|#z75%kln4`W{ST3w zlfStnZ_P-`i9$8LQ16H_?BmfdT3}wJTT)UH{Sxfmk)^W{63IiS4>bVM|JvO*mwd

HvhB^&7Z^={};*=UbtC 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 C&IKF* literal 0 HcmV?d00001 diff --git a/pix/noun-chemical-1892838.svg b/pix/noun-chemical-1892838.svg new file mode 100644 index 0000000..176742a --- /dev/null +++ b/pix/noun-chemical-1892838.svg @@ -0,0 +1 @@ +Created by andrea zudip aggasifrom the Noun Project \ No newline at end of file diff --git a/settings.php b/settings.php new file mode 100644 index 0000000..9a4f9f2 --- /dev/null +++ b/settings.php @@ -0,0 +1,35 @@ +. + +/** + * Plugin administration pages are defined here. + * + * @package tiny_chemdraw + * @category admin + * @copyright 2024 Aniket Kumar + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +if ($hassiteconfig) { + $settings = new admin_settingpage('tiny_chemdraw_settings', new lang_string('pluginname', 'tiny_chemdraw')); + + // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedIf + if ($ADMIN->fulltree) { + // TODO: Define actual plugin settings page and add it to the tree - {@link https://docs.moodle.org/dev/Admin_settings}. + } +} diff --git a/templates/moldraw.mustache b/templates/moldraw.mustache new file mode 100644 index 0000000..93bbaeb --- /dev/null +++ b/templates/moldraw.mustache @@ -0,0 +1,65 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle 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. + + Moodle 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 Moodle. If not, see . +}} +{{! + @template tiny_moldraw/chemdoodle_iframe + + Insert ketcher window for chemical structure drawing. + + Example context (json): + { + + } +}} + +{{< core/modal }} + {{$title}}{{#str}} sketchtitle {{/str}}{{/title}} + {{$body}} +

+ +
+

+
+ +
+
+ + +

+
+ +
+ + +

+
+
+ +
+

+
+ +
+ +
+ +
+ {{/body}} + {{$footer}} + + + {{/footer}} +{{/ core/modal }} diff --git a/version.php b/version.php new file mode 100644 index 0000000..2e053fa --- /dev/null +++ b/version.php @@ -0,0 +1,31 @@ +. + +/** + * Plugin version and other meta-data are defined here. + * + * @package tiny_chemdraw + * @copyright 2024 Aniket Kumar + * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$plugin->component = 'tiny_chemdraw'; +$plugin->release = '0.1.0'; +$plugin->version = 2024041800; +$plugin->requires = 2022112800; +$plugin->maturity = MATURITY_ALPHA;