From c34e4a081440d2164e46d370b129f11a7b14f563 Mon Sep 17 00:00:00 2001 From: zmagod Date: Wed, 26 Jul 2017 13:31:36 +0200 Subject: [PATCH 01/24] fix background worker bug --- app/models/asset.rb | 2 +- config/environments/development.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/models/asset.rb b/app/models/asset.rb index 7430bc473..7d3eb30b3 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -472,7 +472,7 @@ class Asset < ApplicationRecord if errors.size > 1 temp_errors = errors[:file] errors.clear - errors.set(:file, temp_errors) + errors.add(:file, temp_errors) end end diff --git a/config/environments/development.rb b/config/environments/development.rb index ad2246fa1..e4d01050d 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -4,10 +4,10 @@ Rails.application.configure do # In the development environment your application's code is reloaded on # every request. This slows down response time but is perfect for development # since you don't have to restart the web server when you make code changes. - config.cache_classes = false + config.cache_classes = true # Do not eager load code on boot. - config.eager_load = false + config.eager_load = true # Show full error reports and disable caching. config.consider_all_requests_local = true From fbdf96f04bbfcfdfece6b95596f462d4f41abf58 Mon Sep 17 00:00:00 2001 From: Luka Murn Date: Thu, 27 Jul 2017 14:12:28 +0200 Subject: [PATCH 02/24] Remove 3rd party licenses file & fake data generator --- LICENSE-3RD-PARTY.txt | 2410 ----------------------------------- lib/tasks/db_fake_data.rake | 1340 ------------------- 2 files changed, 3750 deletions(-) delete mode 100644 LICENSE-3RD-PARTY.txt delete mode 100644 lib/tasks/db_fake_data.rake diff --git a/LICENSE-3RD-PARTY.txt b/LICENSE-3RD-PARTY.txt deleted file mode 100644 index bafe1b73f..000000000 --- a/LICENSE-3RD-PARTY.txt +++ /dev/null @@ -1,2410 +0,0 @@ ------------------------------------------------------------------------------ - Ruby ------------------------------------------------------------------------------ - -Ruby is copyrighted free software by Yukihiro Matsumoto . -You can redistribute it and/or modify it under either the terms of the -2-clause BSDL (see the file BSDL), or the conditions below: - - 1. You may make and give away verbatim copies of the source form of the - software without restriction, provided that you duplicate all of the - original copyright notices and associated disclaimers. - - 2. You may modify your copy of the software in any way, provided that - you do at least ONE of the following: - - a) place your modifications in the Public Domain or otherwise - make them Freely Available, such as by posting said - modifications to Usenet or an equivalent medium, or by allowing - the author to include your modifications in the software. - - b) use the modified software only within your corporation or - organization. - - c) give non-standard binaries non-standard names, with - instructions on where to get the original software distribution. - - d) make other distribution arrangements with the author. - - 3. You may distribute the software in object code or binary form, - provided that you do at least ONE of the following: - - a) distribute the binaries and library files of the software, - together with instructions (in the manual page or equivalent) - on where to get the original distribution. - - b) accompany the distribution with the machine-readable source of - the software. - - c) give non-standard binaries non-standard names, with - instructions on where to get the original software distribution. - - d) make other distribution arrangements with the author. - - 4. You may modify and include the part of the software into any other - software (possibly commercial). But some files in the distribution - are not written by the author, so that they are not under these terms. - - For the list of those files and their copying conditions, see the - file LEGAL. - - 5. The scripts and library files supplied as input to or produced as - output from the software do not automatically fall under the - copyright of the software, but belong to whomever generated them, - and may be sold commercially, and may be aggregated with this - software. - - 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE. - ------------------------------------------------------------------------------ - Ruby on Rails ------------------------------------------------------------------------------ - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Figaro Ruby Gem ------------------------------------------------------------------------------ - -Copyright (c) 2012 Steve Richert - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - PG Ruby Gem ------------------------------------------------------------------------------ - -Ruby is copyrighted free software by Yukihiro Matsumoto . -You can redistribute it and/or modify it under either the terms of the -2-clause BSDL (see the file BSDL), or the conditions below: - - 1. You may make and give away verbatim copies of the source form of the - software without restriction, provided that you duplicate all of the - original copyright notices and associated disclaimers. - - 2. You may modify your copy of the software in any way, provided that - you do at least ONE of the following: - - a) place your modifications in the Public Domain or otherwise - make them Freely Available, such as by posting said - modifications to Usenet or an equivalent medium, or by allowing - the author to include your modifications in the software. - - b) use the modified software only within your corporation or - organization. - - c) give non-standard binaries non-standard names, with - instructions on where to get the original software distribution. - - d) make other distribution arrangements with the author. - - 3. You may distribute the software in object code or binary form, - provided that you do at least ONE of the following: - - a) distribute the binaries and library files of the software, - together with instructions (in the manual page or equivalent) - on where to get the original distribution. - - b) accompany the distribution with the machine-readable source of - the software. - - c) give non-standard binaries non-standard names, with - instructions on where to get the original software distribution. - - d) make other distribution arrangements with the author. - - 4. You may modify and include the part of the software into any other - software (possibly commercial). But some files in the distribution - are not written by the author, so that they are not under these terms. - - For the list of those files and their copying conditions, see the - file LEGAL. - - 5. The scripts and library files supplied as input to or produced as - output from the software do not automatically fall under the - copyright of the software, but belong to whomever generated them, - and may be sold commercially, and may be aggregated with this - software. - - 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE. - ------------------------------------------------------------------------------ - Devise gem ------------------------------------------------------------------------------ - -Copyright 2009-2016 Plataformatec. http://plataformatec.com.br - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Devise invitable gem ------------------------------------------------------------------------------ - -Copyright (c) 2009 Sergio Cambra - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Bootstrap Sass Gem ------------------------------------------------------------------------------ - -The MIT License (MIT) - -Copyright (c) 2013-2016 Twitter, Inc - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - ------------------------------------------------------------------------------ - Bootstrap ------------------------------------------------------------------------------ - -The MIT License (MIT) - -Copyright (c) 2011-2016 Twitter, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - ------------------------------------------------------------------------------ - Sass Rails Gem ------------------------------------------------------------------------------ - -Copyright (c) 2011-2016 Christopher Eppstein - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Sass ------------------------------------------------------------------------------ - -Copyright (c) 2006-2015 Hampton Catlin, Natalie Weizenbaum, and Chris Eppstein - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Rails Bootstrap Forms Gem ------------------------------------------------------------------------------ - -Copyright 2012-2014 Stephen Potenza - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Yomu Gem ------------------------------------------------------------------------------ - -Copyright (c) 2012 Erol Fornoles - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Apache Tika ------------------------------------------------------------------------------ - -Apache Tika is used by Yomu Gem and is licelsed by Apache License (http://www.apache.org/licenses/). - ------------------------------------------------------------------------------ - Moment-JS Rails Gem ------------------------------------------------------------------------------ - -Copyright 2011 Derek Prior - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - MomentJS ------------------------------------------------------------------------------ - -Copyright (c) 2011-2016 Tim Wood, Iskren Chernev, Moment.js contributors - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Bootstrap 3 Datetime Picker Rails Gem ------------------------------------------------------------------------------ - -Copyright (c) 2014 Trevor Strieber - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Bootstrap 3 Datetime Picker ------------------------------------------------------------------------------ - -The MIT License (MIT) - -Copyright (c) 2015 Jonathan Peterson (@Eonasdan) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ------------------------------------------------------------------------------ - Bootstrap Select Rails Gem ------------------------------------------------------------------------------ - -Copyright (c) 2013 Maciej Krajowski-Kukiel - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Bootstrap Select ------------------------------------------------------------------------------ - -The MIT License (MIT) - -Copyright (c) 2013-2015 bootstrap-select - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ------------------------------------------------------------------------------ - Uglifier Gem ------------------------------------------------------------------------------ - -Copyright (c) 2011 Ville Lautanala - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - UglifyJS ------------------------------------------------------------------------------ - -UglifyJS is released under the BSD license: - -Copyright 2012-2013 (c) Mihai Bazon - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - - * Redistributions of source code must retain the above - copyright notice, this list of conditions and the following - disclaimer. - - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials - provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, -OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR -TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. - ------------------------------------------------------------------------------ - jQuery Turbolinks Gem ------------------------------------------------------------------------------ - -The MIT License - -Copyright (c) 2012 Sasha Koss - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - jQuery Rails Gem ------------------------------------------------------------------------------ - -The MIT License - -Copyright (c) 2010-2016 Andre Arko - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - ------------------------------------------------------------------------------ - jQuery ------------------------------------------------------------------------------ - -Copyright jQuery Foundation and other contributors, https://jquery.org/ - -This software consists of voluntary contributions made by many -individuals. For exact contribution history, see the revision history -available at https://github.com/jquery/jquery - -The following license applies to all parts of this software except as -documented below: - -==== - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -==== - -All files located in the node_modules and external directories are -externally maintained libraries used by this software which have their -own licenses; we recommend you read them, as their terms may differ from -the terms above. - ------------------------------------------------------------------------------ - jQuery UI Rails Gem & jQuery UI ------------------------------------------------------------------------------ - -jQuery UI as well as this gem are licensed under the MIT license (see -below). - -Copyright jQuery Foundation and other contributors, https://jquery.org/ - -This software consists of voluntary contributions made by many -individuals. For exact contribution history, see the revision history -available at https://github.com/jquery/jquery-ui - -The following license applies to all parts of this software except as -documented below: - -==== - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -==== - -Copyright and related rights for sample code are waived via CC0. Sample -code is defined as all source code contained within the demos directory. - -CC0: http://creativecommons.org/publicdomain/zero/1.0/ - -==== - -All files located in the node_modules and external directories are -externally maintained libraries used by this software which have their -own licenses; we recommend you read them, as their terms may differ from -the terms above. - ------------------------------------------------------------------------------ - jQuery scrollto Rails Gem ------------------------------------------------------------------------------ - -This gem packages the scrollTo project for Rails. - -The scrollTo license can be found at https://raw.githubusercontent.com/JohnColvin/jquery-scrollto-rails/master/LICENSE and is copied below: -Apprise was created by Ariel Flesler. The project page is http://archive.plugins.jquery.com/project/ScrollTo. The javascript files claim as of version 1.4.1 that the project is dual licensed under MIT and GPL. - -Please respect the scrollTo licensing. - -The gem code is released under MIT license. - -The MIT License (MIT) - -Copyright (c) 2014 Ariel Flesler (scrollTo author), John Colvin (gem author) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - ------------------------------------------------------------------------------ - HammerJS Rails Gem ------------------------------------------------------------------------------ - -HammerJS is licensed under MIT license. - -The MIT License (MIT) - -Copyright (C) 2011-2014 by Jorik Tangelder (Eight Media) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - IntroJS Rails Gem ------------------------------------------------------------------------------ - -Copyright (c) 2012 Pablo Fernandez - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - IntroJS ------------------------------------------------------------------------------ - -Copyright (C) 2012 Afshin Mehrabani (afshin.meh@gmail.com) -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - JS Cookie Rails Gem ------------------------------------------------------------------------------ - -The MIT License (MIT) - -Copyright (c) 2015 Alessandro Lepore - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - ------------------------------------------------------------------------------ - JS Cookie ------------------------------------------------------------------------------ - -Copyright 2014 Klaus Hartl - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Spin JS Rails Gem ------------------------------------------------------------------------------ - -Copyright (c) 2013 Dmytrii Nagirniak - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - ------------------------------------------------------------------------------ - SpinJS ------------------------------------------------------------------------------ - -Copyright (c) 2011-2015 Felix Gnass [fgnass at gmail dot com] - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Underscore Rails ------------------------------------------------------------------------------ - -The MIT License (MIT) - -Copyright (c) 2013 Robin Wenglewski, Travis Jeffery - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Underscore JS ------------------------------------------------------------------------------ - -Copyright (c) 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative -Reporters & Editors - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Turbolinks Gem ------------------------------------------------------------------------------ - -Copyright 2012-2016 David Heinemeier Hansson - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - SDoc Gem ------------------------------------------------------------------------------ - -Copyright (c) 2014 Zachary Scott, Vladimir Kolesnikov, and Nathan Broadbent - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - - -Darkfish RDoc HTML Generator - -Copyright (c) 2007, 2008, Michael Granger. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the author/s, nor the names of the project's - contributors may be used to endorse or promote products derived from this - software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -RDoc is copyrighted free software. - -You can redistribute it and/or modify it under either the terms of the GPL -version 2 (see the file GPL), or the conditions below: - - 1. You may make and give away verbatim copies of the source form of the - software without restriction, provided that you duplicate all of the - original copyright notices and associated disclaimers. - - 2. You may modify your copy of the software in any way, provided that - you do at least ONE of the following: - - a) place your modifications in the Public Domain or otherwise - make them Freely Available, such as by posting said - modifications to Usenet or an equivalent medium, or by allowing - the author to include your modifications in the software. - - b) use the modified software only within your corporation or - organization. - - c) give non-standard binaries non-standard names, with - instructions on where to get the original software distribution. - - d) make other distribution arrangements with the author. - - 3. You may distribute the software in object code or binary form, - provided that you do at least ONE of the following: - - a) distribute the binaries and library files of the software, - together with instructions (in the manual page or equivalent) - on where to get the original distribution. - - b) accompany the distribution with the machine-readable source of - the software. - - c) give non-standard binaries non-standard names, with - instructions on where to get the original software distribution. - - d) make other distribution arrangements with the author. - - 4. You may modify and include the part of the software into any other - software (possibly commercial). But some files in the distribution - are not written by the author, so that they are not under these terms. - - For the list of those files and their copying conditions, see the - file LEGAL. - - 5. The scripts and library files supplied as input to or produced as - output from the software do not automatically fall under the - copyright of the software, but belong to whomever generated them, - and may be sold commercially, and may be aggregated with this - software. - - 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE. - ------------------------------------------------------------------------------ - BCrypt Gem ------------------------------------------------------------------------------ - -(The MIT License) - -Copyright 2007-2011: - -* Coda Hale - -C implementation of the BCrypt algorithm by Solar Designer and placed in the -public domain. -jBCrypt is Copyright (c) 2006 Damien Miller . - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Logging Gem ------------------------------------------------------------------------------ - -The MIT License - -Copyright (c) 2015 Tim Pease - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Aspector Gem ------------------------------------------------------------------------------ - -Copyright (c) 2011 Guoliang Cao, Maciej Mensfeld - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - RGL Gem & RGL ------------------------------------------------------------------------------ - -RGL is Copyright (c) 2002,2004,2005,2008,2013,2015 by Horst Duchene. It is free software, and may be redistributed under the terms specified in the README file of the Ruby distribution. - ------------------------------------------------------------------------------ - Nested Form Fields Gem ------------------------------------------------------------------------------ - -Copyright (c) 2012 Nico Ritsche - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - AJAX Datatables Rails Gem ------------------------------------------------------------------------------ - -Copyright (c) 2012 Joel Quenneville - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Datatables JS ------------------------------------------------------------------------------ - -MIT license -Copyright (C) 2008-2016, SpryMedia Ltd. - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Commit param routing gem ------------------------------------------------------------------------------ - -Copyright (c) 2013 Senthil V S - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Kaminari Gem ------------------------------------------------------------------------------ - -Copyright (c) 2011 Akira Matsuda - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - I18n-JS Gem ------------------------------------------------------------------------------ - -(The MIT License) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Roo Gem ------------------------------------------------------------------------------ - -Copyright (c) 2008-2014 Thomas Preymesser, Ben Woosley - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Wicked PDF Gem ------------------------------------------------------------------------------ - -Copyright (c) 2008 Miles Z. Sterrett - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - wkhtmltopdf ------------------------------------------------------------------------------ - - GNU LESSER 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. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser 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 -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. - ------------------------------------------------------------------------------ - Remotipart Gem ------------------------------------------------------------------------------ - -Copyright (c) 2009 Greg Leppert - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Quill ------------------------------------------------------------------------------ - -Copyright (c) 2014, Jason Chen -Copyright (c) 2013, salesforce.com -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright -notice, this list of conditions and the following disclaimer in the -documentation and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ------------------------------------------------------------------------------ - Faker Gem ------------------------------------------------------------------------------ - -Copyright (c) 2007-2010 Benjamin Curtis - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Paperclip Gem ------------------------------------------------------------------------------ - -Copyright (c) 2008-2016 Jon Yurek and thoughtbot, inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - ------------------------------------------------------------------------------ - AWS-SDK Gem ------------------------------------------------------------------------------ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - ------------------------------------------------------------------------------ - AWS-SDK V1 Gem ------------------------------------------------------------------------------ - -Copyright 2011-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. - -Licensed under the Apache License, Version 2.0 (the "License"). You -may not use this file except in compliance with the License. A copy of -the License is located at - - http://aws.amazon.com/apache2.0/ - -or in the "license" file accompanying this file. This file is -distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF -ANY KIND, either express or implied. See the License for the specific -language governing permissions and limitations under the License. - ------------------------------------------------------------------------------ - Delayed Job ActiveRecord Gem ------------------------------------------------------------------------------ - -Copyright (c) 2005 Tobias Lütke - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOa AND NONINFRINGEMENT. IN NO EVENT SaALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Delayed Job ------------------------------------------------------------------------------ - -Copyright (c) 2005 Tobias Luetke - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOa AND -NONINFRINGEMENT. IN NO EVENT SaALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Devise Async Gem ------------------------------------------------------------------------------ - -Copyright (c) 2012 Marcelo Silveira - -MIT License - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Byebug Gem ------------------------------------------------------------------------------ - - -Copyright (c) David Rodríguez -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. - ------------------------------------------------------------------------------ - Web Console Gem ------------------------------------------------------------------------------ - -Copyright 2014-2016 Charlie Somerville, Genadi Samokovarov, Guillermo Iguaran and Ryan Dao - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Puma Ruby Server ------------------------------------------------------------------------------ - -Some code copyright (c) 2005, Zed Shaw -Copyright (c) 2011, Evan Phoenix -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above copyright notice - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. -* Neither the name of the Evan Phoenix nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ------------------------------------------------------------------------------ - Rails 12factor Gem ------------------------------------------------------------------------------ - -The MIT License (MIT) - -Copyright (c) 2013,2014 Heroku - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - ------------------------------------------------------------------------------ - TZInfo::Data Gem ------------------------------------------------------------------------------ - -Copyright (c) 2005-2016 Philip Ross - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - ------------------------------------------------------------------------------ - SkyLight Gem ------------------------------------------------------------------------------ - -All other components of this product, except where otherwise noted, are Copyright (c) 2013-2014 Tilde, Inc. All rights reserved. - -Certain inventions disclosed in this file may be claimed within patents owned or patent applications filed by Tilde, Inc. or third parties. - -Subject to the terms of this notice, Tilde grants you a nonexclusive, nontransferable license, without the right to sublicense, to (a) install and execute one copy of these files on any number of workstations owned or controlled by you and (b) distribute verbatim copies of these files to third parties. As a condition to the foregoing grant, you must provide this notice along with each copy you distribute and you must not remove, alter, or obscure this notice. All other use, reproduction, modification, distribution, or other exploitation of these files is strictly prohibited, except as may be set forth in a separate written license agreement between you and Tilde. The terms of any such license agreement will control over this notice. The license stated above will be automatically terminated and revoked if you exceed its scope or violate any of the terms of this notice. - -This License does not grant permission to use the trade names, trademarks, service marks, or product names of Tilde, except as required for reasonable and customary use in describing the origin of this file and reproducing the content of this notice. You may not mark or brand this file with any trade name, trademarks, service marks, or product names other than the original brand (if any) provided by Tilde. - -Unless otherwise expressly agreed by Tilde in a separate written license agreement, these files are provided AS IS, WITHOUT WARRANTY OF ANY KIND, including without any implied warranties of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, or NON-INFRINGEMENT. As a condition to your use of these files, you are solely responsible for such use. Tilde will have no liability to you for direct, indirect, consequential, incidental, special, or punitive damages or for lost profits or data. - -Other Licenses -ActiveSupport - -Copyright (c) 2005-2014 David Heinemeier Hansson - -Released under the MIT License. - -Original source at https://github.com/rails/rails/tree/master/activesupport. - -HighLine - -Copyright (c) 2014 James Edward Gray II, Gregory Brown, et al. - -Distributed under the user's choice of the GPL Version 2 or the Ruby software license. - -Original source at https://github.com/JEG2/highline. - -Thor - -Copyright (c) 2008 Yehuda Katz, Eric Hodel, et al. - -Released under the MIT License. - -Original source at https://github.com/erikhuda/thor. - -ThreadSafe - -Copyright (c) 2014 Charles Oliver Nutter, thedarkone, et al. - -Distributed under Apache License, Version 2.0, January 2004 - -Original source at https://github.com/ruby-concurrency/thread_safe. - ------------------------------------------------------------------------------ - i18n_missing_keys Rake Task License ------------------------------------------------------------------------------ - -Copyright (c) 2010 Jakob Skjerning - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ------------------------------------------------------------------------------ - bootstrap-colorselector.js License ------------------------------------------------------------------------------ - -Copyright (c) 2013 Flaute - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - ------------------------------------------------------------------------------ - canvas-to-blob.js ------------------------------------------------------------------------------ - -The JavaScript Canvas to Blob script is released under the MIT license. - ------------------------------------------------------------------------------ - eventPause.js License ------------------------------------------------------------------------------ - -eventPause.js v 1.0.0 -Author: sudhanshu yadav -s-yadav.github.com -Copyright (c) 2013 Sudhanshu Yadav. -Dual licensed under the MIT and GPL licenses - ------------------------------------------------------------------------------ - Handsontable JS ------------------------------------------------------------------------------ - -(The MIT License) - -Copyright (c) 2012-2014 Marcin Warpechowski -Copyright (c) 2015 Handsoncode sp. z o.o. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - jQuery mousewheel JS ------------------------------------------------------------------------------ - -Copyright jQuery Foundation and other contributors -https://jquery.org/ - -This software consists of voluntary contributions made by many -individuals. For exact contribution history, see the revision history -available at https://github.com/jquery/jquery-mousewheel - -The following license applies to all parts of this software except as -documented below: - -==== - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -==== - -All files located in the node_modules and external directories are -externally maintained libraries used by this software which have their -own licenses; we recommend you read them, as their terms may differ from -the terms above. - ------------------------------------------------------------------------------ - jQuery UI Touch Punch ------------------------------------------------------------------------------ - -Project page: http://touchpunch.furf.com/ - -Copyright (c) 2012 David Furfero - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - JSNetworkX ------------------------------------------------------------------------------ - -JSNetworkX is distributed with the BSD license - -Copyright (C) 2012 Felix Kling - - -NetworkX code is distributed with the BSD license - - -Copyright (C) 2004-2011, NetworkX Developers -Aric Hagberg -Dan Schult -Pieter Swart -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - -* Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - -* Neither the name of the NetworkX Developers nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ------------------------------------------------------------------------------ - jsPlumb Community Edition License ------------------------------------------------------------------------------ - -Copyright (c) 2010 - 2014 jsPlumb, http://jsplumbtoolkit.com/ - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Sortable.min.js ------------------------------------------------------------------------------ - -Copyright 2013-2016 Lebedev Konstantin ibnRubaXa@gmail.com http://rubaxa.github.io/Sortable/ - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - Simple Sidebar HTML Template ------------------------------------------------------------------------------ - -Start Bootstrap - Simple Sidebar HTML Template (http://startbootstrap.com) -Code licensed under the Apache License v2.0. -For details, see http://www.apache.org/licenses/LICENSE-2.0. - ------------------------------------------------------------------------------ - Creative Loading Effects ------------------------------------------------------------------------------ - -By Codrops -http://tympanus.net/codrops/2013/09/18/creative-loading-effects/ - -Licensing & Terms of Use - -The resources on Codrops can be used freely in personal and commercial projects. Please note, that most of the tutorials and resources are experimental and not ready for production, but made for inspiration and demonstration purpose only. - -The resources on Codrops can be used in websites, web apps and web templates intended for sale. You don’t have to link back to us if it vitiates your work but we appreciate any credit. - -You are not allowed to take our work “as-is” and sell it, redistribute or re-publish it (with the exception of forking our GitHub repos), or sell “pluginized” versions of it. - -If you plan to create free WordPress, jQuery, Joomla, etc. plugins out of our scripts, please credit us in a fair way and link to the respective article on Codrops. - -Please, respect the licenses of the resources (audio, video or images) that we often use in our demos. We always indicate the license in the article and link to the owner/creator in both, article and demo. - -If you write about some of our work we would like you to add a link back to us. You are free to copy excerpts but please do not copy entire articles (e.g. RSS feed scraping), we put our heart into this work. Don’t re-publish our demos and our ZIP files, and don’t link directly to any ZIP file, link to the article instead. - -Please contact us, if you’d like to translate articles and re-publish them. - -Summarized, use it freely, integrate it, make it your own, but don’t copy and paste our work and sell it or claim that it’s yours, stay fair. - ------------------------------------------------------------------------------ - bootstrap-tagsinput ------------------------------------------------------------------------------ - -The MIT License (MIT) - -Copyright (c) 2013 Tim Schlechter - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ - typeahead.js ------------------------------------------------------------------------------ - -Copyright (c) 2013-2014 Twitter, Inc - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - ------------------------------------------------------------------------------ - jszip ------------------------------------------------------------------------------ - -The MIT License -Copyright (c) 2009-2016 Stuart Knightley, David Duponchel, Franz Buchinger, António Afonso - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/lib/tasks/db_fake_data.rake b/lib/tasks/db_fake_data.rake deleted file mode 100644 index 28a616168..000000000 --- a/lib/tasks/db_fake_data.rake +++ /dev/null @@ -1,1340 +0,0 @@ -require "#{Rails.root}/app/utilities/users_generator" -require "#{Rails.root}/app/utilities/renaming_util" -require "#{Rails.root}/test/helpers/fake_test_helper" -include UsersGenerator -include RenamingUtil -include FakeTestHelper - -namespace :db do - NR_TEAMS = 4 - NR_USERS = 100 - NR_SAMPLE_TYPES = 20 - NR_SAMPLE_GROUPS = 20 - NR_CUSTOM_FIELDS = 20 - NR_SAMPLES = 100 - NR_PROTOCOLS = 20 - NR_PROTOCOL_KEYWORDS = 20 - NR_PROJECTS = 3 - NR_EXPERIMENTS = 4 - NR_MODULE_GROUPS = 4 - NR_MODULES = 4 - NR_STEPS = 3 - NR_RESULTS = 4 - NR_REPORTS = 4 - NR_COMMENTS = 10 - RATIO_USER_TEAMS = 0.5 - NR_MAX_USER_TEAMS = 20 - RATIO_CUSTOM_FIELDS = 0.7 - RATIO_SAMPLE_CUSTOM_FIELDS = 0.6 - RATIO_PROTOCOL_KEYWORDS = 0.3 - THRESHOLD_PROTOCOL_IN_MODULE_LINKED = 0.5 - THRESHOLD_PROTOCOL_PUBLIC = 0.6 - THRESHOLD_PROTOCOL_ARCHIVED = 0.2 - NR_MAX_USER_PROJECTS = 15 - RATIO_USER_PROJECTS = 0.5 - RATIO_COMMENTS = 0.7 - NR_MAX_USER_MODULES = 15 - RATIO_USER_MODULES = 0.5 - NR_MAX_SAMPLE_MODULES = 10 - RATIO_SAMPLE_MODULES = 0.7 - RATIO_MODULE_MODULE_GROUPS = 0.8 - RATIO_EDGES = 0.7 - RATIO_STEP_COMPLETED = 0.5 - NR_MAX_STEP_ATTACHMENTS = 2 - RATIO_STEP_ATTACHMENTS = 0.2 - NR_MAX_CHECKLIST_ITEMS = 20 - RATIO_CHECKLIST_ITEM = 0.2 - RATIO_CHECKLIST_ITEM_CHECKED = 0.5 - RATIO_RESULT_ARCHIVED = 0.2 - RATIO_REPORT_ELEMENTS = 0.75 - - THRESHOLD_ARCHIVED = 0.2 - THRESHOLD_RESTORED = 0.9 - - MIN_FILE_SIZE = 0.01 - MAX_FILE_SIZE = 0.1 - - desc "Drops the database, sets it up and inserts fake data for " + - "the current RAILS_ENV. WARNING: THIS WILL ERASE ALL " + - "CURRENT DATA IN THE DATABASE." - task :fake => :environment do - Rake::Task["db:drop"].reenable - Rake::Task["db:drop"].invoke - Rake::Task["db:setup"].reenable - Rake::Task["db:setup"].invoke - Rake::Task["db:fake:generate"].reenable - Rake::Task["db:fake:generate"].invoke - end - - namespace :fake do - desc "Generates fake data & inserts it into database for the " + - "current RAILS_ENV." - task :generate => :environment do - require 'rgl/base' - require 'rgl/adjacency' - require 'rgl/topsort' - - puts "Verbose? (Y/n)" - res = $stdin.gets.to_s.downcase.strip - unless res.in?(["", "y", "n"]) then - puts "Invalid parameter, exiting" - return - end - verbose = res.in?(["", "y"]) - - puts "Simple seeding? (Y/n)" - res = $stdin.gets.to_s.downcase.strip - unless res.in?(["", "y", "n"]) then - puts "Invalid parameter, exiting" - return - end - simple = res.in?(["", "y"]) - - if simple - puts "Choose the size of generated dataset(T - tiny, " + - "s - small, m - medium, l - large, h -huge)" - res = $stdin.gets.to_s.downcase.strip - unless res.in?(["", "t", "s", "m", "l", "h"]) then - puts "Invalid parameter, exiting" - return - end - - case res - when "", "t" - factor = 0.5 - when "s" - factor = 1 - when "m" - factor = 5 - when "l" - factor = 20 - when "h" - factor = 100 - end - - nr_team = NR_TEAMS * factor - nr_users = NR_USERS * factor - nr_sample_types = NR_SAMPLE_TYPES * factor - nr_sample_groups = NR_SAMPLE_GROUPS * factor - nr_custom_fields = NR_CUSTOM_FIELDS * factor - nr_samples = NR_SAMPLES * factor - nr_protocols = NR_PROTOCOLS * factor - nr_protocol_keywords = NR_PROTOCOL_KEYWORDS * factor - nr_projects = NR_PROJECTS * factor - nr_experiments = NR_EXPERIMENTS * factor - nr_module_groups = NR_MODULE_GROUPS * factor - nr_modules = NR_MODULES * factor - nr_steps = NR_STEPS * factor - nr_results = NR_RESULTS * factor - nr_reports = NR_REPORTS * factor - nr_comments = NR_COMMENTS * factor - else - puts "Type in the number of seeded teams" - nr_team = $stdin.gets.to_i - puts "Type in the number of seeded users" - nr_users = $stdin.gets.to_i - puts "Type in the number of seeded sample types " + - "for each team" - nr_sample_types = $stdin.gets.to_i - puts "Type in the number of seeded sample groups for " + - "each team" - nr_sample_groups = $stdin.gets.to_i - puts "Type in the max. number of seeded custom fields " + - "for each team" - nr_custom_fields = $stdin.gets.to_i - puts "Type in the number of seeded samples for each team" - nr_samples = $stdin.gets.to_i - puts "Type in the number of seeded protocols for each team" - nr_protocols = $stdin.gets.to_i - puts "Type in the number of seeded protocol keywords for each team" - nr_protocol_keywords = $stdin.gets.to_i - puts "Type in the number of seeded projects for each team" - nr_projects = $stdin.gets.to_i - puts "Type in the number of seeded experiments for each project" - nr_experiments = $stdin.gets.to_i - puts "Type in the number of seeded workflows for each experiment" - nr_module_groups = $stdin.gets.to_i - puts "Type in the number of seeded modules for each experiment" - nr_modules = $stdin.gets.to_i - puts "Type in the number of seeded steps for each module" - nr_steps = $stdin.gets.to_i - puts "Type in the number of seeded results for each module" - nr_results = $stdin.gets.to_i - puts "Type in the number of seeded reports for each project" - nr_reports = $stdin.gets.to_i - puts "Type in the max. number of seeded comments for each " + - "commentable item" - nr_comments = $stdin.gets.to_i - end - - begin - ActiveRecord::Base.transaction do - - puts "Generating fake teams..." - taken_team_names = [] - for _ in 1..nr_team - begin - name = Faker::University.name - end while name.in? taken_team_names - taken_team_names << name - - Team.create( - name: name, - description: rand >= 0.7 ? Faker::Lorem.sentence : nil - ) - end - - all_teams = Team.all - - puts "Generating fake users..." - taken_emails = [] - for _ in 1..nr_users - begin - if rand >= 0.8 - name = generate_got_name - else - name = Faker::Name.name - end - email_name = name.downcase.remove(".").split(" ").join(".") - password = Faker::Internet.password(10, 20) - email = Faker::Internet.free_email(email_name) - end while email.in? taken_emails - taken_emails << email - - user = create_user( - name, - email, - password, - true, - nil, - [] - ) - user.update( - confirmed_at: Faker::Date.backward(30), - ) - if verbose then - puts " Generated user #{name} (email: #{email}, " + - "password: #{password})" - end - - # Randomly assign user to teams - taken_team_ids = [] - for _ in 1..[NR_MAX_USER_TEAMS, all_teams.count].min - if rand <= RATIO_USER_TEAMS then - begin - team = pluck_random(all_teams) - end while team.id.in? taken_team_ids - taken_team_ids << team.id - - UserTeam.create( - user: user, - team: team, - role: rand(0..2) - ) - end - end - end - - puts "Generating fake sample types..." - all_teams.find_each do |team| - for _ in 1..nr_sample_types - SampleType.create( - name: Faker::Commerce.department(4), - team: team - ) - end - end - - puts "Generating fake sample groups..." - all_teams.find_each do |team| - for _ in 1..nr_sample_groups - SampleGroup.create( - name: Faker::Commerce.color, - team: team, - color: generate_color - ) - end - end - - puts "Generating fake custom fields..." - all_teams.find_each do |team| - for _ in 1..nr_custom_fields - if rand <= RATIO_CUSTOM_FIELDS then - CustomField.create( - name: Faker::Team.state, - team: team, - user: pluck_random(team.users) - ) - end - end - end - - puts "Generating fake samples..." - all_teams.find_each do |team| - for _ in 1..nr_samples - sample = Sample.create( - name: Faker::Book.title, - team: team, - user: pluck_random(team.users), - sample_type: pluck_random(team.sample_types), - sample_group: pluck_random(team.sample_groups) - ) - - # Add some custom fields to sample - team.custom_fields.find_each do |cf| - if rand <= RATIO_SAMPLE_CUSTOM_FIELDS then - SampleCustomField.create( - sample: sample, - custom_field: cf, - value: Faker::Team.state - ) - end - end - end - end - - puts "Generating fake protocol keywords" - all_teams.find_each do |team| - taken_kw_names = [] - for _ in 1..nr_protocol_keywords - begin - name = Faker::Book.genre - end while name.in? taken_kw_names - taken_kw_names << name - ProtocolKeyword.create( - team: team, - name: name - ) - end - end - - puts "Generating fake repository protocols..." - all_teams.find_each do |team| - for _ in 1..nr_protocols - protocol = generate_fake_protocol(team, - nil, - nr_steps, - nr_comments) - - if verbose then - puts " Generated protocol #{protocol.name}" - end - end - end - - puts "Generating fake projects..." - all_teams.find_each do |team| - taken_project_names = [] - for _ in 1..nr_projects - begin - name = Faker::Company.name[0..29] - end while name.in? taken_project_names - taken_project_names << name - - author = pluck_random(team.users) - created_at = Faker::Time.backward(500) - last_modified_by = pluck_random(team.users) - archived_by = pluck_random(team.users) - archived_on = Faker::Time.between(created_at, DateTime.now) - restored_by = pluck_random(team.users) - restored_on = Faker::Time.between(archived_on, DateTime.now) - status = random_status - - project = Project.create( - visibility: rand(0..1), - name: name, - due_date: nil, - team: team, - created_by: author, - created_at: created_at, - last_modified_by: last_modified_by, - archived: status == :archived, - archived_by: status.in?([:archived, :restored]) ? - archived_by : nil, - archived_on: status.in?([:archived, :restored]) ? - archived_on : nil, - restored_by: status == :restored ? restored_by : nil, - restored_on: status == :restored ? restored_on : nil - ) - # Automatically assign project author onto project - UserProject.create( - user: author, - project: project, - role: 0, - created_at: created_at - ) - - # Activities - Activity.create( - type_of: :create_project, - user: author, - project: project, - message: I18n.t( - "activities.create_project", - user: author.full_name, - project: project.name - ), - created_at: created_at - ) - if status.in?([:archived, :restored]) then - Activity.create( - type_of: :archive_project, - user: archived_by, - project: project, - message: I18n.t( - "activities.archive_project", - user: archived_by.full_name, - project: project.name - ), - created_at: archived_on - ) - end - if status == :restored then - Activity.create( - type_of: :restore_project, - user: restored_by, - project: project, - message: I18n.t( - "activities.restore_project", - user: restored_by.full_name, - project: project.name - ), - created_at: restored_on - ) - end - - # Assign users onto the project - taken_user_ids = [] - for _ in 2..[NR_MAX_USER_PROJECTS, team.users.count].min - if rand <= RATIO_USER_PROJECTS - begin - user = pluck_random(team.users) - end while user.id.in? taken_user_ids - taken_user_ids << user.id - - assigned_on = Faker::Time.backward(500) - assigned_by = pluck_random(project.users) - up = UserProject.create( - user: user, - project: project, - role: rand(0..3), - created_at: assigned_on, - assigned_by: assigned_by - ) - Activity.create( - type_of: :assign_user_to_project, - user: assigned_by, - project: project, - message: I18n.t( - "activities.assign_user_to_project", - assigned_user: user.full_name, - role: up.role_str, - project: project.name, - assigned_by_user: assigned_by.full_name - ), - created_at: assigned_on - ) - end - end - - # Add some comments - for _ in 1..nr_comments - generate_fake_project_comment(project) if rand <= RATIO_COMMENTS - end - end - end - - puts "Generating fake experiments..." - Project.find_each do |project| - for _ in 1..nr_experiments - status = random_status - created_at = Faker::Time.backward(500) - archived_by = pluck_random(project.users) - archived_on = Faker::Time.between(created_at, DateTime.now) - restored_by = pluck_random(project.users) - restored_on = Faker::Time.between(archived_on, DateTime.now) - - author = pluck_random(project.users) - Experiment.create( - name: Faker::Hacker.noun, - description: Faker::Hipster.sentence, - project: project, - created_at: created_at, - created_by: author, - last_modified_by: author, - archived: status.in?([:active, :restored]), - archived_on: status.in?([:archived, :restored]) ? - archived_on : nil, - archived_by: status.in?([:archived, :restored]) ? - archived_by : nil, - restored_on: status == :restored ? restored_on : nil, - restored_by: status == :restored ? restored_by : nil - ) - end - end - - puts "Generating fake workflows..." - Experiment.find_each do |experiment| - for _ in 1..nr_module_groups - MyModuleGroup.create( - name: Faker::Hacker.noun, - experiment: experiment - ) - end - end - - puts "Generating fake modules..." - total_experiment = Experiment.count - Experiment.find_each.with_index do |experiment, i| - if verbose then - puts " Generating modules for experiment #{experiment.name} " + - "(#{i + 1} of #{total_experiment})..." - end - project = experiment.project - taken_pos = [] - for _ in 1..nr_modules - begin - x = rand(0..nr_modules) * 32 - y = rand(0..nr_modules) * 16 - end while [x, y].in? taken_pos - taken_pos << [x, y] - - status = random_status - author = pluck_random(team.users) - created_at = Faker::Time.backward(500) - archived_by = pluck_random(team.users) - archived_on = Faker::Time.between(created_at, DateTime.now) - restored_by = pluck_random(team.users) - restored_on = Faker::Time.between(archived_on, DateTime.now) - - my_module = MyModule.create( - name: Faker::Hacker.verb, - created_by: author, - created_at: created_at, - due_date: rand <= 0.5 ? - Faker::Time.forward(500) : nil, - description: rand <= 0.5 ? - Faker::Hacker.say_something_smart : nil, - x: x, - y: y, - experiment: experiment, - my_module_group: status == :archived ? - nil : - (rand <= RATIO_MODULE_MODULE_GROUPS ? - pluck_random(experiment.my_module_groups) : nil - ), - archived: status == :archived, - archived_on: status.in?([:archived, :restored]) ? - archived_on : nil, - archived_by: status.in?([:archived, :restored]) ? - archived_by : nil, - restored_on: status == :restored ? restored_on : nil, - restored_by: status == :restored ? restored_by : nil - ) - - # Activities - Activity.create( - type_of: :create_module, - user: author, - project: my_module.experiment.project, - my_module: my_module, - message: I18n.t( - "activities.create_module", - user: author.full_name, - module: my_module.name - ), - created_at: created_at - ) - if status.in?([:archived, :restored]) then - Activity.create( - type_of: :archive_module, - user: archived_by, - project: my_module.experiment.project, - my_module: my_module, - message: I18n.t( - "activities.archive_module", - user: archived_by.full_name, - module: my_module.name - ), - created_at: archived_on - ) - end - if status == :restored then - Activity.create( - type_of: :restore_module, - user: restored_by, - project: my_module.experiment.project, - my_module: my_module, - message: I18n.t( - "activities.restore_module", - user: restored_by.full_name, - module: my_module.name - ), - created_at: restored_on - ) - end - - if verbose then - puts " Generated module #{my_module.name}" - end - - # Assign some users onto module - taken_user_ids = [] - for _ in 1..[NR_MAX_USER_MODULES, project.users.count].min - if rand <= RATIO_USER_MODULES then - begin - user = pluck_random(project.users) - end while user.id.in? taken_user_ids - taken_user_ids << user.id - - assigned_on = Faker::Time.backward(500) - assigned_by = pluck_random(my_module.experiment.project.users) - UserMyModule.create( - user: user, - my_module: my_module, - assigned_by: pluck_random(project.users), - created_at: assigned_on - ) - Activity.create( - type_of: :assign_user_to_module, - user: assigned_by, - project: my_module.experiment.project, - my_module: my_module, - message: I18n.t( - "activities.assign_user_to_module", - assigned_user: user.full_name, - module: my_module.name, - assigned_by_user: assigned_by.full_name - ), - created_at: assigned_on - ) - end - end - - # Assign some samples onto module - taken_sample_ids = [] - for _ in 1..[ - NR_MAX_SAMPLE_MODULES, - project.team.samples.count - ].min - if rand <= RATIO_SAMPLE_MODULES then - begin - sample = pluck_random(project.team.samples) - end while sample.id.in? taken_sample_ids - taken_sample_ids << sample.id - - SampleMyModule.create( - sample: sample, - my_module: my_module - ) - end - end - - # Add some comments - for _ in 1..nr_comments - generate_fake_module_comment(my_module) if rand <= RATIO_COMMENTS - end - end - - # Generate some connections between modules - experiment.my_module_groups.find_each do |my_module_group| - if my_module_group.my_modules.empty? or - my_module_group.my_modules.count == 1 - # If any module group doesn't contain - # any modules (or has only 1 module), remove it - my_module_group.destroy - else - # Make connections between project modules, - # keeping in mind not to generate cycles - n = my_module_group.my_modules.count - max_edges = (n - 1) * n / 2 - - dg = RGL::DirectedAdjacencyGraph.new - for _ in 1..max_edges - if rand <= RATIO_EDGES - begin - m1 = pluck_random(my_module_group.my_modules) - m2 = pluck_random(my_module_group.my_modules) - end while ( - m1 == m2 or - dg.has_edge?(m1.id, m2.id) - ) - - # Only add edge if it won't make graph cyclic - dg.add_edge(m1.id, m2.id) - if dg.acyclic? - Connection.create( - input_id: m1.id, - output_id: m2.id - ) - else - dg.remove_edge(m1.id, m2.id) - end - end - end - - # Set order number for each module in group - topsort = dg.topsort_iterator.to_a - my_module_group.my_modules.each do |mm| - if topsort.include? mm.id - mm.workflow_order = topsort.find_index(mm.id) - mm.save! - end - end - end - end - end - - puts 'Generating fake module protocols...' - Experiment.find_each do |experiment| - experiment.my_modules.find_each do |my_module| - generate_fake_protocol(experiment.project.team, - my_module, - nr_steps, - nr_comments) - end - end - - puts "Generating fake module results..." - Experiment.find_each do |experiment| - experiment.my_modules.find_each do |my_module| - for _ in 1..nr_results - user = pluck_random(my_module.users) - created_at = Faker::Time.backward(500) - archived_on = Faker::Time.between(created_at, DateTime.now) - restored_on = Faker::Time.between(archived_on, DateTime.now) - status = random_status - - result = Result.new( - name: Faker::Hacker.abbreviation[0..49], - my_module: my_module, - user: user, - created_at: created_at, - archived: status == :archived, - archived_by: status.in?([:archived, :restored]) ? - user : nil, - archived_on: status.in?([:archived, :restored]) ? - archived_on : nil, - restored_by: status == :restored ? user : nil, - restored_on: status == :restored ? restored_on : nil - ) - - type = [:text, :asset, :table][rand(0..2)] - case type - when :text - result.result_text = ResultText.new( - text: Faker::Hipster.paragraph, - ) - str = "activities.add_text_result" - str2 = "activities.archive_text_result" - when :asset - result.asset = Asset.new( - file: generate_file(rand(MIN_FILE_SIZE..MAX_FILE_SIZE)), - created_by: result.user - ) - str = "activities.add_asset_result" - str2 = "activities.archive_asset_result" - when :table - result.table = Table.new( - contents: generate_table_contents(rand(30), rand(150)), - created_by: result.user - ) - str = "activities.add_table_result" - str2 = "activities.archive_table_result" - end - - result.save - - # Add activities - Activity.create( - type_of: :add_result, - project: experiment.project, - my_module: my_module, - user: user, - created_at: created_at, - message: I18n.t( - str, - user: user.full_name, - result: result.name - ) - ) - if status.in?([:archived, :restored]) then - Activity.create( - type_of: :archive_result, - user: user, - project: experiment.project, - my_module: my_module, - message: I18n.t( - str2, - user: user.full_name, - result: result.name - ), - created_at: archived_on - ) - end - # Currently, there is no way to restore archived results - - # Add some comments - for _ in 1..nr_comments - generate_fake_result_comment(result) if rand <= RATIO_COMMENTS - end - end - end - end - - puts "Generating fake reports..." - Experiment.find_each do |experiment| - project = experiment.project - for _ in 1..nr_reports - taken_project_names = [] - begin - name = Faker::Company.bs - user = pluck_random(project.users) - end while [user, name].in? taken_project_names - taken_project_names << [user, name] - - report = Report.create( - name: name, - description: Faker::Hipster.sentence, - project: project, - user: user - ) - - # Generate the oh-so-many report elements - ReportElement.create( - sort_order: 0, - position: 0, - report: report, - type_of: :project_header - ) - experiment.my_modules.each do |my_module| - if rand <= RATIO_REPORT_ELEMENTS then - re_my_module = ReportElement.create( - sort_order: rand <= 0.5 ? 0 : 1, - position: 0, - report: report, - type_of: :my_module, - my_module: my_module - ) - - my_module.protocol.completed_steps.each do |step| - if rand <= RATIO_REPORT_ELEMENTS then - re_step = ReportElement.create( - sort_order: rand <= 0.5 ? 0 : 1, - position: 0, - report: report, - type_of: :step, - step: step, - parent: re_my_module - ) - - step.checklists.each do |checklist| - if rand <= RATIO_REPORT_ELEMENTS then - ReportElement.create( - sort_order: rand <= 0.5 ? 0 : 1, - position: 0, - report: report, - type_of: :step_checklist, - checklist: checklist, - parent: re_step - ) - end - end - step.assets.each do |asset| - if rand <= RATIO_REPORT_ELEMENTS then - ReportElement.create( - sort_order: rand <= 0.5 ? 0 : 1, - position: 0, - report: report, - type_of: :step_asset, - asset: asset, - parent: re_step - ) - end - end - step.tables.each do |table| - if rand <= RATIO_REPORT_ELEMENTS then - ReportElement.create( - sort_order: rand <= 0.5 ? 0 : 1, - position: 0, - report: report, - type_of: :step_table, - table: table, - parent: re_step - ) - end - end - if rand <= RATIO_REPORT_ELEMENTS then - ReportElement.create( - sort_order: rand <= 0.5 ? 0 : 1, - position: 0, - report: report, - type_of: :step_comments, - step: step, - parent: re_step - ) - end - end - end - - my_module.results.each do |result| - if rand <= RATIO_REPORT_ELEMENTS then - if result.is_asset - type_of = :result_asset - elsif result.is_table - type_of = :result_table - else - type_of = :result_text - end - re_result = ReportElement.create( - sort_order: rand <= 0.5 ? 0 : 1, - position: 0, - report: report, - type_of: type_of, - result: result, - parent: re_my_module - ) - - if rand <= RATIO_REPORT_ELEMENTS then - ReportElement.create( - sort_order: rand <= 0.5 ? 0 : 1, - position: 0, - report: report, - type_of: :result_comments, - result: result, - parent: re_result - ) - end - end - end - - if rand <= RATIO_REPORT_ELEMENTS then - ReportElement.create( - sort_order: rand <= 0.5 ? 0 : 1, - position: 0, - report: report, - type_of: :my_module_activity, - my_module: my_module, - parent: re_my_module - ) - end - - if rand <= RATIO_REPORT_ELEMENTS then - ReportElement.create( - sort_order: rand <= 0.5 ? 0 : 1, - position: 0, - report: report, - type_of: :my_module_samples, - my_module: my_module, - parent: re_my_module - ) - end - end - end - - # Shuffle the report - shuffle_report_elements( - report.report_elements.where(parent: nil) - ) - end - end - - end - - # Now, at the end, add additional "private" team - # to each user - User.find_each do |user| - create_private_user_team(user, Constants::DEFAULT_PRIVATE_TEAM_NAME) - end - - # Generate thumbnails of all experiments - Experiment.find_each do |experiment| - experiment.generate_workflow_img - end - - # Calculate space taken by each team; this must - # be done in a separate transaction because the estimated - # asset sizes are calculated in after_commit, which is done - # after the first transaction is completed - ActiveRecord::Base.transaction do - puts 'Calculating team sizes...' - Team.find_each do |team| - team.calculate_space_taken - team.save - end - end - rescue ActiveRecord::ActiveRecordError, - ArgumentError, ActiveRecord::RecordNotSaved => e - puts "Error seeding fake data, transaction reverted" - puts "Output: #{e.inspect}" - puts e.backtrace.join("\n") - end - end - end - - def generate_fake_protocol( - team, - my_module, - nr_steps, - nr_comments - ) - protocol = nil - if my_module.present? - protocol = my_module.protocol - users = my_module.experiment.project.users - author = pluck_random(users) - if rand <= THRESHOLD_PROTOCOL_IN_MODULE_LINKED && - (parent = pluck_random( - team.protocols.where(protocol_type: [ - Protocol.protocol_types[:in_repository_private], - Protocol.protocol_types[:in_repository_public] - ])) - ).present? - protocol.protocol_type = :linked - protocol.added_by = author - protocol.parent = parent - protocol.parent_updated_at = parent.updated_at - else - protocol.protocol_type = :unlinked - end - protocol.my_module = my_module - else - protocol = Protocol.new - users = team.users - author = pluck_random(users) - val = rand - if val > THRESHOLD_PROTOCOL_ARCHIVED - if val > THRESHOLD_PROTOCOL_PUBLIC - protocol.protocol_type = :in_repository_public - protocol.published_on = Faker::Time.backward(500) - else - protocol.protocol_type = :in_repository_private - end - else - protocol.protocol_type = :in_repository_archived - protocol.archived_by = author - protocol.archived_on = Faker::Time.backward(500) - end - protocol.added_by = author - protocol.authors = Faker::Book.author - protocol.description = Faker::Lorem.paragraph(2) - end - protocol.name = Faker::Hacker.ingverb - protocol.team = team - - if protocol.invalid? then - rename_record(protocol, :name) - end - - protocol.save! - - team.protocol_keywords.find_each do |kw| - if rand <= RATIO_PROTOCOL_KEYWORDS - ProtocolProtocolKeyword.create( - protocol: protocol, - protocol_keyword: kw - ) - end - end - - protocol.reload - if protocol.linked? - # For linked protocols, simply copy their parents' contents - protocol.load_from_repository(protocol.parent, author) - else - # Generate fake protocol data - for i in 1..nr_steps - created_at = Faker::Time.backward(500) - completed = protocol.in_repository? ? false : (rand <= RATIO_STEP_COMPLETED) - completed_on = completed ? - Faker::Time.between(created_at, DateTime.now) : nil - - step = Step.create( - created_at: created_at, - name: Faker::Hacker.ingverb, - description: Faker::Hacker.say_something_smart, - position: i - 1, - completed: completed, - user: pluck_random(users), - protocol: protocol, - completed_on: completed_on - ) - if protocol.in_module? - Activity.create( - type_of: :create_step, - project: my_module.experiment.project, - my_module: my_module, - user: step.user, - created_at: created_at, - message: I18n.t( - "activities.create_step", - user: step.user.full_name, - step: i, - step_name: step.name - ) - ) - end - if completed then - Activity.create( - type_of: :complete_step, - project: my_module.experiment.project, - my_module: my_module, - user: step.user, - created_at: completed_on, - message: I18n.t( - "activities.complete_step", - user: step.user.full_name, - step: i, - step_name: step.name, - completed: i, - all: i - ) - ) - end - - # Add checklists - for _ in 1..NR_MAX_STEP_ATTACHMENTS - if rand <= RATIO_STEP_ATTACHMENTS then - checklist = Checklist.create( - name: Faker::Hacker.noun, - step: step, - created_by: step.user, - ) - - # Add checklist items - for j in 1..NR_MAX_CHECKLIST_ITEMS - if rand <= RATIO_CHECKLIST_ITEM then - checked = protocol.in_repository? ? false : (rand <= RATIO_CHECKLIST_ITEM_CHECKED) - checked_on = Faker::Time.backward(500) - ci = ChecklistItem.create( - created_at: checked_on, - text: Faker::Hipster.sentence, - checklist: checklist, - checked: checked, - created_by: step.user - ) - if checked then - Activity.create( - type_of: :check_step_checklist_item, - project: my_module.experiment.project, - my_module: my_module, - user: step.user, - created_at: checked_on, - message: I18n.t( - "activities.check_step_checklist_item", - user: step.user.full_name, - checkbox: ci.text, - completed: j, - all: j, - step: i, - step_name: step.name - ) - ) - end - end - end - end - end - - # Add assets - for _ in 1..NR_MAX_STEP_ATTACHMENTS - if rand <= RATIO_STEP_ATTACHMENTS then - asset = Asset.create( - file: generate_file(rand(MIN_FILE_SIZE..MAX_FILE_SIZE)), - estimated_size: 0, - file_present: true, - created_by: step.user - ) - StepAsset.create( - step: step, - asset: asset - ) - end - end - - # Add tables - for _ in 1..NR_MAX_STEP_ATTACHMENTS - if rand <= RATIO_STEP_ATTACHMENTS then - table = Table.create( - contents: - generate_table_contents(rand(30), rand(150)), - created_by: step.user - ) - StepTable.create( - step: step, - table: table - ) - end - end - - # Add some comments (only on protocols on module) - if protocol.in_module? then - for _ in 1..nr_comments - if rand <= RATIO_COMMENTS - user = pluck_random(users) - created_at = Faker::Time.backward(500) - StepComment.create( - user: user, - message: Faker::Hipster.sentence, - created_at: created_at, - step: step - ) - Activity.create( - type_of: :add_comment_to_step, - project: my_module.experiment.project, - my_module: my_module, - user: user, - created_at: created_at, - message: I18n.t( - "activities.add_comment_to_step", - user: user.full_name, - step: i, - step_name: step.name - ) - ) - end - end - end - end - end - - return protocol.reload - end - - def shuffle_report_elements(report_elements) - if report_elements.blank? or report_elements.count == 0 - return - end - - header = report_elements.find_by(type_of: :project_header) - if header.present? - header.position = 0 - header.save - i = 1 - else - i = 0 - end - - ids_map = (i..(report_elements.count - 1)).to_a.shuffle - for i in i..(report_elements.count - 1) - re = report_elements[i] - re.position = ids_map[i] - re.save - end - - # Recursively shuffle children - report_elements.each do |re2| - if re2.children.count > 0 - shuffle_report_elements(re2.children) - end - end - end - - def generate_fake_project_comment(project) - user = pluck_random(project.users) - created_at = Faker::Time.backward(500) - ProjectComment.create( - user: user, - message: Faker::Hipster.sentence, - created_at: created_at, - project: project - ) - Activity.create( - type_of: :add_comment_to_project, - user: user, - project: project, - created_at: created_at, - message: I18n.t('activities.add_comment_to_project', - user: user.full_name, - project: project.name) - ) - end - - def generate_fake_module_comment(my_module) - user = pluck_random(my_module.experiment.project.users) - created_at = Faker::Time.backward(500) - TaskComment.create( - user: user, - message: Faker::Hipster.sentence, - created_at: created_at, - my_module: my_module - ) - Activity.create( - type_of: :add_comment_to_module, - user: user, - project: my_module.experiment.project, - my_module: my_module, - created_at: created_at, - message: I18n.t('activities.add_comment_to_module', - user: user.full_name, - module: my_module.name) - ) - end - - def generate_fake_result_comment(result) - user = pluck_random(result.my_module.experiment.project.users) - created_at = Faker::Time.backward(500) - ResultComment.create( - user: user, - message: Faker::Hipster.sentence, - created_at: created_at, - result: result - ) - Activity.create( - type_of: :add_comment_to_result, - project: result.my_module.experiment.project, - my_module: result.my_module, - user: user, - created_at: created_at, - message: I18n.t( - 'activities.add_comment_to_result', - user: user.full_name, - result: result.name - ) - ) - end - - def generate_fake_step_comment(step) - user = pluck_random(step.protocol.my_module.experiment.project.users) - created_at = Faker::Time.backward(500) - StepComment.create( - user: user, - message: Faker::Hipster.sentence, - created_at: created_at, - step: step - ) - Activity.create( - type_of: :add_comment_to_step, - project: step.protocol.my_module.experiment.project, - my_module: step.protocol.my_module, - user: user, - created_at: created_at, - message: I18n.t( - "activities.add_comment_to_step", - user: user.full_name, - step: step.position + 1, - step_name: step.name - ) - ) - end - - # WARNING: This only works on PostgreSQL - def pluck_random(scope) - scope.order("RANDOM()").first - end - - # Randomly determine whether project/module/result is active (0), - # archived (1), or already restored (2) - def random_status - val = rand - status = :active - if val > THRESHOLD_ARCHIVED - if val > THRESHOLD_RESTORED - status = :archived - end - else - status = :restored - end - status - end -end From 03a7440136ab3e32a5cbd0072b53cad19e7a8288 Mon Sep 17 00:00:00 2001 From: Luka Murn Date: Thu, 27 Jul 2017 14:26:44 +0200 Subject: [PATCH 03/24] Remove SkyLight stuff (we're not using it any more) --- Gemfile | 1 - Gemfile.lock | 3 --- Makefile | 2 +- config/skylight.yml | 3 --- 4 files changed, 1 insertion(+), 8 deletions(-) delete mode 100644 config/skylight.yml diff --git a/Gemfile b/Gemfile index 0a074d9f9..51f706288 100644 --- a/Gemfile +++ b/Gemfile @@ -85,7 +85,6 @@ end group :production do gem 'puma' gem 'rails_12factor' - gem 'skylight' end group :test do diff --git a/Gemfile.lock b/Gemfile.lock index aeeb3b107..243390fe6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -294,8 +294,6 @@ GEM actionmailer (>= 3.2.6, < 6) actionpack (>= 3.2.6, < 6) devise (>= 3.2, < 6) - skylight (0.10.0) - activesupport (>= 3.0.0) sourcemap (0.1.1) spinjs-rails (1.4) rails (>= 3.1) @@ -403,7 +401,6 @@ DEPENDENCIES shoulda-matchers (>= 3.0.1) silencer simple_token_authentication (~> 1.0) - skylight sneaky-save! spinjs-rails starscope diff --git a/Makefile b/Makefile index bc41aaeee..0108c54f8 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ all: docker database heroku: @heroku buildpacks:remove https://github.com/ddollar/heroku-buildpack-multi.git @heroku buildpacks:set https://github.com/ddollar/heroku-buildpack-multi.git - @echo "Set environment variables, DATABASE_URL, RAILS_SERVE_STATIC_FILES, RAKE_ENV, RAILS_ENV, SECRET_KEY_BASE, SKYLIGHT_AUTHENTICATION" + @echo "Set environment variables, DATABASE_URL, RAILS_SERVE_STATIC_FILES, RAKE_ENV, RAILS_ENV, SECRET_KEY_BASE" docker: @docker-compose build diff --git a/config/skylight.yml b/config/skylight.yml deleted file mode 100644 index 0bf0b90e6..000000000 --- a/config/skylight.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -# The authentication token for the application. -authentication: <%= ENV["SKYLIGHT_AUTHENTICATION"] ?> From d90ca1b934a9988c7bc6123c98cb3539edccc317 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Zrim=C5=A1ek?= Date: Wed, 2 Aug 2017 16:49:53 +0200 Subject: [PATCH 04/24] Fixed slow exporting of repositories - JS listeners which triggered function responsible for providing export data was bound more than once. [SCI-1481] --- .../repositories/repository_datatable.js | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/app/assets/javascripts/repositories/repository_datatable.js b/app/assets/javascripts/repositories/repository_datatable.js index be818201a..f868deffb 100644 --- a/app/assets/javascripts/repositories/repository_datatable.js +++ b/app/assets/javascripts/repositories/repository_datatable.js @@ -728,21 +728,26 @@ var RepositoryDatatable = (function(global) { if (rowsSelected.length === 1) { $('#editRepositoryRecord').prop('disabled', false); $('#editRepositoryRecord').removeClass('disabled'); + + // If we switched from 2 selections to 1, then this is not needed + var events = $._data($('#exportRepositoriesButton').get(0), 'events'); + if (!events || !events.click) { + $('#exportRepositoriesButton').removeClass('disabled'); + $('#exportRepositoriesButton').prop('disabled', false); + $('#exportRepositoriesButton').on('click', function() { + $('#exportRepositoryModal').modal('show'); + }); + $('#export-repositories').on('click', function() { + animateSpinner(null, true); + $('#form-export').submit(); + }); + } } else { $('#editRepositoryRecord').prop('disabled', true); $('#editRepositoryRecord').addClass('disabled'); } $('#deleteRepositoryRecordsButton').prop('disabled', false); $('#deleteRepositoryRecordsButton').removeClass('disabled'); - $('#exportRepositoriesButton').removeClass('disabled'); - $('#exportRepositoriesButton').prop('disabled', false); - $('#exportRepositoriesButton').on('click', function() { - $('#exportRepositoryModal').modal('show'); - }); - $('#export-repositories').on('click', function() { - animateSpinner(null, true); - $('#form-export').submit(); - }); $('#assignRepositoryRecords').removeClass('disabled'); $('#assignRepositoryRecords').prop('disabled', false); $('#unassignRepositoryRecords').removeClass('disabled'); From 77fdaaeb2e6db490bf3e27971902e22ff378e351 Mon Sep 17 00:00:00 2001 From: Luka Murn Date: Thu, 3 Aug 2017 11:28:33 +0200 Subject: [PATCH 05/24] Add versions Rake file --- lib/tasks/versions.rake | 193 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 lib/tasks/versions.rake diff --git a/lib/tasks/versions.rake b/lib/tasks/versions.rake new file mode 100644 index 000000000..d3d9ffa60 --- /dev/null +++ b/lib/tasks/versions.rake @@ -0,0 +1,193 @@ +namespace :versions do + ADJECTIVES = { + 'a': + ['aback', 'abaft', 'abandoned', 'abashed', 'aberrant', 'abhorrent', 'abiding', 'abject', 'ablaze', 'able', 'abnormal', 'aboard', 'aboriginal', 'abortive', 'abounding', 'abrasive', 'abrupt', 'absent', 'absolute', 'absorbed', 'absorbing', 'abstracted', 'absurd', 'abundant', 'abusive', 'academic', 'acceptable', 'accessible', 'accidental', 'acclaimed', 'accomplished', 'accurate', 'aching', 'acid', 'acidic', 'acoustic', 'acrid', 'acrobatic', 'active', 'actual', 'actually', 'ad hoc', 'adamant', 'adaptable', 'addicted', 'adept', 'adhesive', 'adjoining', 'admirable', 'admired', 'adolescent', 'adorable', 'adored', 'advanced', 'adventurous', 'affectionate', 'afraid', 'aged', 'aggravating', 'aggressive', 'agile', 'agitated', 'agonizing', 'agreeable', 'ahead', 'ajar', 'alarmed', 'alarming', 'alcoholic', 'alert', 'alienated', 'alike', 'alive', 'all', 'alleged', 'alluring', 'aloof', 'altruistic', 'amazing', 'ambiguous', 'ambitious', 'amiable', 'ample', 'amuck', 'amused', 'amusing', 'anchored', 'ancient', 'ancient', 'angelic', 'angry', 'angry', 'anguished', 'animated', 'annoyed', 'annoying', 'annual', 'another', 'antique', 'antsy', 'anxious', 'any', 'apathetic', 'appetizing', 'apprehensive', 'appropriate', 'apt', 'aquatic', 'arctic', 'arid', 'aromatic', 'arrogant', 'artistic', 'ashamed', 'aspiring', 'assorted', 'assured', 'astonishing', 'athletic', 'attached', 'attentive', 'attractive', 'auspicious', 'austere', 'authentic', 'authorized', 'automatic', 'available', 'avaricious', 'average', 'awake', 'aware', 'awesome', 'awful', 'awkward', 'axiomatic'], + 'b': + ['babyish', 'back', 'bad', 'baggy', 'barbarous', 'bare', 'barren', 'bashful', 'basic', 'batty', 'bawdy', 'beautiful', 'beefy', 'befitting', 'belated', 'belligerent', 'beloved', 'beneficial', 'bent', 'berserk', 'best', 'better', 'bewildered', 'bewitched', 'big', 'big-hearted', 'billowy', 'biodegradable', 'bite-sized', 'biting', 'bitter', 'bizarre', 'black', 'black-and-white', 'bland', 'blank', 'blaring', 'bleak', 'blind', 'blissful', 'blond', 'bloody', 'blue', 'blue-eyed', 'blushing', 'bogus', 'boiling', 'bold', 'bony', 'boorish', 'bored', 'boring', 'bossy', 'both', 'bouncy', 'boundless', 'bountiful', 'bowed', 'brainy', 'brash', 'brave', 'brawny', 'breakable', 'breezy', 'brief', 'bright', 'brilliant', 'brisk', 'broad', 'broken', 'bronze', 'brown', 'bruised', 'bubbly', 'bulky', 'bumpy', 'buoyant', 'burdensome', 'burly', 'bustling', 'busy', 'buttery', 'buzzing'], + 'c': + ['cagey', 'calculating', 'callous', 'calm', 'candid', 'canine', 'capable', 'capital', 'capricious', 'carefree', 'careful', 'careless', 'caring', 'cautious', 'cavernous', 'ceaseless', 'celebrated', 'certain', 'changeable', 'charming', 'cheap', 'cheeky', 'cheerful', 'cheery', 'chemical', 'chief', 'childlike', 'chilly', 'chivalrous', 'chubby', 'chunky', 'circular', 'clammy', 'classic', 'classy', 'clean', 'clear', 'clear-cut', 'clever', 'cloistered', 'close', 'closed', 'cloudy', 'clueless', 'clumsy', 'cluttered', 'coarse', 'coherent', 'cold', 'colorful', 'colorless', 'colossal', 'colossal', 'combative', 'comfortable', 'common', 'compassionate', 'competent', 'complete', 'complex', 'complicated', 'composed', 'concerned', 'concrete', 'condemned', 'condescending', 'confused', 'conscious', 'considerate', 'constant', 'contemplative', 'content', 'conventional', 'convincing', 'convoluted', 'cooing', 'cooked', 'cool', 'cooperative', 'coordinated', 'corny', 'corrupt', 'costly', 'courageous', 'courteous', 'cowardly', 'crabby', 'crafty', 'craven', 'crazy', 'creamy', 'creative', 'creepy', 'criminal', 'crisp', 'critical', 'crooked', 'crowded', 'cruel', 'crushing', 'cuddly', 'cultivated', 'cultured', 'cumbersome', 'curious', 'curly', 'curved', 'curvy', 'cut', 'cute', 'cylindrical', 'cynical'], + 'd': + ['daffy', 'daily', 'damaged', 'damaging', 'damp', 'dangerous', 'dapper', 'dapper', 'daring', 'dark', 'darling', 'dashing', 'dazzling', 'dead', 'deadly', 'deadpan', 'deafening', 'dear', 'dearest', 'debonair', 'decayed', 'deceitful', 'decent', 'decimal', 'decisive', 'decorous', 'deep', 'deeply', 'defeated', 'defective', 'defenseless', 'defensive', 'defiant', 'deficient', 'definite', 'delayed', 'delectable', 'delicate', 'delicious', 'delightful', 'delirious', 'demanding', 'demonic', 'dense', 'dental', 'dependable', 'dependent', 'depraved', 'depressed', 'deranged', 'descriptive', 'deserted', 'despicable', 'detailed', 'determined', 'devilish', 'devoted', 'didactic', 'different', 'difficult', 'digital', 'dilapidated', 'diligent', 'dim', 'diminutive', 'dimpled', 'dimwitted', 'direct', 'direful', 'dirty', 'disagreeable', 'disastrous', 'discreet', 'discrete', 'disfigured', 'disguised', 'disgusted', 'disgusting', 'dishonest', 'disillusioned', 'disloyal', 'dismal', 'dispensable', 'distant', 'distinct', 'distorted', 'distraught', 'distressed', 'disturbed', 'divergent', 'dizzy', 'domineering', 'dopey', 'doting', 'double', 'doubtful', 'downright', 'drab', 'draconian', 'drafty', 'drained', 'dramatic', 'dreary', 'droopy', 'drunk', 'dry', 'dual', 'dull', 'dull', 'dusty', 'dutiful', 'dynamic', 'dysfunctional'], + 'e': + ['each', 'eager', 'early', 'earnest', 'earsplitting', 'earthy', 'easy', 'easy-going', 'eatable', 'economic', 'ecstatic', 'edible', 'educated', 'efficacious', 'efficient', 'eight', 'elaborate', 'elastic', 'elated', 'elderly', 'electric', 'elegant', 'elementary', 'elfin', 'elite', 'elliptical', 'emaciated', 'embarrassed', 'embellished', 'eminent', 'emotional', 'empty', 'enchanted', 'enchanting', 'encouraging', 'endurable', 'energetic', 'enlightened', 'enormous', 'enraged', 'entertaining', 'enthusiastic', 'entire', 'envious', 'envious', 'equable', 'equal', 'equatorial', 'erect', 'erratic', 'essential', 'esteemed', 'ethereal', 'ethical', 'euphoric', 'evanescent', 'evasive', 'even', 'evergreen', 'everlasting', 'every', 'evil', 'exalted', 'exasperated', 'excellent', 'excitable', 'excited', 'exciting', 'exclusive', 'exemplary', 'exhausted', 'exhilarated', 'exotic', 'expensive', 'experienced', 'expert', 'extensive', 'extra-large', 'extraneous', 'extra-small', 'extroverted', 'exuberant', 'exultant'], + 'f': + ['fabulous', 'faded', 'failing', 'faint', 'fair', 'faithful', 'fake', 'fallacious', 'false', 'familiar', 'famous', 'fanatical', 'fancy', 'fantastic', 'far', 'faraway', 'far-flung', 'far-off', 'fascinated', 'fast', 'fat', 'fatal', 'fatherly', 'faulty', 'favorable', 'favorite', 'fearful', 'fearless', 'feeble', 'feigned', 'feisty', 'feline', 'female', 'feminine', 'fertile', 'festive', 'few', 'fickle', 'fierce', 'filthy', 'fine', 'finicky', 'finished', 'firm', 'first', 'firsthand', 'fitting', 'five', 'fixed', 'flagrant', 'flaky', 'flamboyant', 'flashy', 'flat', 'flawed', 'flawless', 'flickering', 'flimsy', 'flippant', 'floppy', 'flowery', 'flufy', 'fluid', 'flustered', 'fluttering', 'foamy', 'focused', 'fond', 'foolhardy', 'foolish', 'forceful', 'foregoing', 'forgetful', 'forked', 'formal', 'forsaken', 'forthright', 'fortunate', 'four', 'fragile', 'fragrant', 'frail', 'frank', 'frantic', 'frayed', 'free', 'freezing', 'French', 'frequent', 'fresh', 'fretful', 'friendly', 'frightened', 'frightening', 'frigid', 'frilly', 'frivolous', 'frizzy', 'front', 'frosty', 'frothy', 'frozen', 'frugal', 'fruitful', 'frustrating', 'full', 'fumbling', 'fumbling', 'functional', 'funny', 'furry', 'furtive', 'fussy', 'future', 'futuristic', 'fuzzy'], + 'g': + ['gabby', 'gainful', 'gamy', 'gaping', 'gargantuan', 'garrulous', 'gaseous', 'gaudy', 'general', 'general', 'generous', 'gentle', 'genuine', 'ghastly', 'giant', 'giddy', 'gifted', 'gigantic', 'giving', 'glamorous', 'glaring', 'glass', 'gleaming', 'gleeful', 'glib', 'glistening', 'glittering', 'gloomy', 'glorious', 'glossy', 'glum', 'godly', 'golden', 'good', 'good-natured', 'goofy', 'gorgeous', 'graceful', 'gracious', 'grand', 'grandiose', 'grandiose', 'granular', 'grateful', 'gratis', 'grave', 'gray', 'greasy', 'great', 'greedy', 'green', 'gregarious', 'grey', 'grieving', 'grim', 'grimy', 'gripping', 'grizzled', 'groovy', 'gross', 'grotesque', 'grouchy', 'grounded', 'growing', 'growling', 'grown', 'grubby', 'gruesome', 'grumpy', 'guarded', 'guiltless', 'guilty', 'gullible', 'gummy', 'gusty', 'guttural'], + 'h': + ['habitual', 'hairy', 'half', 'half', 'hallowed', 'halting', 'handmade', 'handsome', 'handsomely', 'handy', 'hanging', 'hapless', 'happy', 'happy-go-lucky', 'hard', 'hard-to-find', 'harebrained', 'harmful', 'harmless', 'harmonious', 'harsh', 'hasty', 'hateful', 'haunting', 'heady', 'healthy', 'heartbreaking', 'heartfelt', 'hearty', 'heavenly', 'heavy', 'hefty', 'hellish', 'helpful', 'helpless', 'hesitant', 'hidden', 'hideous', 'high', 'highfalutin', 'high-level', 'high-pitched', 'hilarious', 'hissing', 'historical', 'hoarse', 'holistic', 'hollow', 'homeless', 'homely', 'honest', 'honorable', 'honored', 'hopeful', 'horrible', 'horrific', 'hospitable', 'hot', 'huge', 'hulking', 'humble', 'humdrum', 'humiliating', 'humming', 'humongous', 'humorous', 'hungry', 'hurried', 'hurt', 'hurtful', 'hushed', 'husky', 'hypnotic', 'hysterical'], + 'i': + ['icky', 'icy', 'ideal', 'ideal', 'idealistic', 'identical', 'idiotic', 'idle', 'idolized', 'ignorant', 'ill', 'illegal', 'ill-fated', 'ill-informed', 'illiterate', 'illustrious', 'imaginary', 'imaginative', 'immaculate', 'immaterial', 'immediate', 'immense', 'imminent', 'impartial', 'impassioned', 'impeccable', 'imperfect', 'imperturbable', 'impish', 'impolite', 'important', 'imported', 'impossible', 'impractical', 'impressionable', 'impressive', 'improbable', 'impure', 'inborn', 'incandescent', 'incomparable', 'incompatible', 'incompetent', 'incomplete', 'inconclusive', 'inconsequential', 'incredible', 'indelible', 'indolent', 'industrious', 'inexpensive', 'inexperienced', 'infamous', 'infantile', 'infatuated', 'inferior', 'infinite', 'informal', 'innate', 'innocent', 'inquisitive', 'insecure', 'insidious', 'insignificant', 'insistent', 'instinctive', 'instructive', 'insubstantial', 'intelligent', 'intent', 'intentional', 'interesting', 'internal', 'international', 'intrepid', 'intrigued', 'invincible', 'irate', 'ironclad', 'irresponsible', 'irritable', 'irritating', 'itchy'], + 'j': + ['jaded', 'jagged', 'jam-packed', 'jaunty', 'jazzy', 'jealous', 'jittery', 'jobless', 'joint', 'jolly', 'jovial', 'joyful', 'joyous', 'jubilant', 'judicious', 'juicy', 'jumbled', 'jumbo', 'jumpy', 'jumpy', 'junior', 'juvenile'], + 'k': + ['kaleidoscopic', 'kaput', 'keen', 'key', 'kind', 'kindhearted', 'kindly', 'klutzy', 'knobby', 'knotty', 'knowing', 'knowledgeable', 'known', 'kooky', 'kosher'], + 'l': + ['labored', 'lackadaisical', 'lacking', 'lame', 'lame', 'lamentable', 'languid', 'lanky', 'large', 'last', 'lasting', 'late', 'laughable', 'lavish', 'lawful', 'lazy', 'leading', 'leafy', 'lean', 'learned', 'left', 'legal', 'legitimate', 'lethal', 'level', 'lewd', 'light', 'lighthearted', 'likable', 'like', 'likeable', 'likely', 'limited', 'limp', 'limping', 'linear', 'lined', 'liquid', 'literate', 'little', 'live', 'lively', 'livid', 'living', 'loathsome', 'lone', 'lonely', 'long', 'longing', 'long-term', 'loose', 'lopsided', 'lost', 'loud', 'loutish', 'lovable', 'lovely', 'loving', 'low', 'lowly', 'loyal', 'lucky', 'ludicrous', 'lumbering', 'luminous', 'lumpy', 'lush', 'lustrous', 'luxuriant', 'luxurious', 'lying', 'lyrical'], + 'm': + ['macabre', 'macho', 'mad', 'maddening', 'made-up', 'madly', 'magenta', 'magical', 'magnificent', 'majestic', 'major', 'makeshift', 'male', 'malicious', 'mammoth', 'maniacal', 'many', 'marked', 'married', 'marvelous', 'masculine', 'massive', 'material', 'materialistic', 'mature', 'meager', 'mealy', 'mean', 'measly', 'meaty', 'medical', 'mediocre', 'medium', 'meek', 'melancholy', 'mellow', 'melodic', 'melted', 'memorable', 'menacing', 'merciful', 'mere', 'merry', 'messy', 'metallic', 'mighty', 'mild', 'military', 'milky', 'mindless', 'miniature', 'minor', 'minty', 'minute', 'miscreant', 'miserable', 'miserly', 'misguided', 'mistaken', 'misty', 'mixed', 'moaning', 'modern', 'modest', 'moist', 'moldy', 'momentous', 'monstrous', 'monthly', 'monumental', 'moody', 'moral', 'mortified', 'motherly', 'motionless', 'mountainous', 'muddled', 'muddy', 'muffled', 'multicolored', 'mundane', 'mundane', 'murky', 'mushy', 'musty', 'mute', 'muted', 'mysterious'], + 'n': + ['naive', 'nappy', 'narrow', 'nasty', 'natural', 'naughty', 'nauseating', 'nautical', 'near', 'neat', 'nebulous', 'necessary', 'needless', 'needy', 'negative', 'neglected', 'negligible', 'neighboring', 'neighborly', 'nervous', 'nervous', 'new', 'next', 'nice', 'nice', 'nifty', 'nimble', 'nine', 'nippy', 'nocturnal', 'noiseless', 'noisy', 'nonchalant', 'nondescript', 'nonsensical', 'nonstop', 'normal', 'nostalgic', 'nosy', 'notable', 'noted', 'noteworthy', 'novel', 'noxious', 'null', 'numb', 'numberless', 'numerous', 'nutritious', 'nutty'], + 'o': + ['oafish', 'obedient', 'obeisant', 'obese', 'oblivious', 'oblong', 'obnoxious', 'obscene', 'obsequious', 'observant', 'obsolete', 'obtainable', 'obvious', 'occasional', 'oceanic', 'odd', 'oddball', 'offbeat', 'offensive', 'official', 'oily', 'old', 'old-fashioned', 'omniscient', 'one', 'onerous', 'only', 'open', 'opposite', 'optimal', 'optimistic', 'opulent', 'orange', 'orderly', 'ordinary', 'organic', 'original', 'ornate', 'ornery', 'ossified', 'other', 'our', 'outgoing', 'outlandish', 'outlying', 'outrageous', 'outstanding', 'oval', 'overconfident', 'overcooked', 'overdue', 'overjoyed', 'overlooked', 'overrated', 'overt', 'overwrought'], + 'p': + ['painful', 'painstaking', 'palatable', 'pale', 'paltry', 'panicky', 'panoramic', 'parallel', 'parched', 'parsimonious', 'partial', 'passionate', 'past', 'pastel', 'pastoral', 'pathetic', 'peaceful', 'penitent', 'peppery', 'perfect', 'perfumed', 'periodic', 'perky', 'permissible', 'perpetual', 'perplexed', 'personal', 'pertinent', 'pesky', 'pessimistic', 'petite', 'petty', 'petty', 'phobic', 'phony', 'physical', 'picayune', 'piercing', 'pink', 'piquant', 'pitiful', 'placid', 'plain', 'plaintive', 'plant', 'plastic', 'plausible', 'playful', 'pleasant', 'pleased', 'pleasing', 'plucky', 'plump', 'plush', 'pointed', 'pointless', 'poised', 'polished', 'polite', 'political', 'pompous', 'poor', 'popular', 'portly', 'posh', 'positive', 'possessive', 'possible', 'potable', 'powerful', 'powerless', 'practical', 'precious', 'premium', 'present', 'present', 'prestigious', 'pretty', 'previous', 'pricey', 'prickly', 'primary', 'prime', 'pristine', 'private', 'prize', 'probable', 'productive', 'profitable', 'profuse', 'proper', 'protective', 'proud', 'prudent', 'psychedelic', 'psychotic', 'public', 'puffy', 'pumped', 'punctual', 'pungent', 'puny', 'pure', 'purple', 'purring', 'pushy', 'pushy', 'putrid', 'puzzled', 'puzzling'], + 'q': + ['quack', 'quaint', 'quaint', 'qualified', 'quarrelsome', 'quarterly', 'queasy', 'querulous', 'questionable', 'quick', 'quickest', 'quick-witted', 'quiet', 'quintessential', 'quirky', 'quixotic', 'quixotic', 'quizzical'], + 'r': + ['rabid', 'racial', 'radiant', 'ragged', 'rainy', 'rambunctious', 'rampant', 'rapid', 'rare', 'rash', 'raspy', 'ratty', 'raw', 'ready', 'real', 'realistic', 'reasonable', 'rebel', 'recent', 'receptive', 'reckless', 'recondite', 'rectangular', 'red', 'redundant', 'reflecting', 'reflective', 'regal', 'regular', 'reliable', 'relieved', 'remarkable', 'reminiscent', 'remorseful', 'remote', 'repentant', 'repulsive', 'required', 'resolute', 'resonant', 'respectful', 'responsible', 'responsive', 'revolving', 'rewarding', 'rhetorical', 'rich', 'right', 'righteous', 'rightful', 'rigid', 'ringed', 'ripe', 'ritzy', 'roasted', 'robust', 'romantic', 'roomy', 'rosy', 'rotating', 'rotten', 'rotund', 'rough', 'round', 'rowdy', 'royal', 'rubbery', 'ruddy', 'rude', 'rundown', 'runny', 'rural', 'rustic rusty', 'ruthless'], + 's': + ['sable', 'sad', 'safe', 'salty', 'same', 'sandy', 'sane', 'sarcastic', 'sardonic', 'sassy', 'satisfied', 'satisfying', 'savory', 'scaly', 'scandalous', 'scant', 'scarce', 'scared', 'scary', 'scattered', 'scented', 'scholarly', 'scientific', 'scintillating', 'scornful', 'scratchy', 'scrawny', 'screeching', 'second', 'secondary', 'second-hand', 'secret', 'secretive', 'sedate', 'seemly', 'selective', 'self-assured', 'selfish', 'self-reliant', 'sentimental', 'separate', 'serene', 'serious', 'serpentine', 'several', 'severe', 'shabby', 'shadowy', 'shady', 'shaggy', 'shaky', 'shallow', 'shameful', 'shameless', 'sharp', 'shimmering', 'shiny', 'shivering', 'shocked', 'shocking', 'shoddy', 'short', 'short-term', 'showy', 'shrill', 'shut', 'shy', 'sick', 'silent', 'silky', 'silly', 'silver', 'similar', 'simple', 'simplistic', 'sincere', 'sinful', 'single', 'six', 'sizzling', 'skeletal', 'skillful', 'skinny', 'sleepy', 'slight', 'slim', 'slimy', 'slippery', 'sloppy', 'slow', 'slushy', 'small', 'smarmy', 'smart', 'smelly', 'smiling', 'smoggy', 'smooth', 'smug', 'snappy', 'snarling', 'sneaky', 'sniveling', 'snobbish', 'snoopy', 'snotty', 'sociable', 'soft', 'soggy', 'solid', 'somber', 'some', 'sophisticated', 'sordid', 'sore', 'sorrowful', 'soulful', 'soupy', 'sour', 'sour', 'Spanish', 'sparkling', 'sparse', 'special', 'specific', 'spectacular', 'speedy', 'spherical', 'spicy', 'spiffy', 'spiky', 'spirited', 'spiritual', 'spiteful', 'splendid', 'spooky', 'spotless', 'spotted', 'spotty', 'spry', 'spurious', 'squalid', 'square', 'squeaky', 'squealing', 'squeamish', 'squiggly', 'stable', 'staid', 'stained', 'staking', 'stale', 'standard', 'standing', 'starchy', 'stark', 'starry', 'statuesque', 'steadfast', 'steady', 'steel', 'steep', 'stereotyped', 'sticky', 'stiff', 'stimulating', 'stingy', 'stormy', 'stout', 'straight', 'strange', 'strict', 'strident', 'striking', 'striped', 'strong', 'studious', 'stunning', 'stunning', 'stupendous', 'stupid', 'sturdy', 'stylish', 'subdued', 'submissive', 'subsequent', 'substantial', 'subtle', 'suburban', 'successful', 'succinct', 'succulent', 'sudden', 'sugary', 'sulky', 'sunny', 'super', 'superb', 'superficial', 'superior', 'supportive', 'supreme', 'sure-footed', 'surprised', 'suspicious', 'svelte', 'swanky', 'sweaty', 'sweet', 'sweltering', 'swift', 'sympathetic', 'symptomatic', 'synonymous'], + 't': + ['taboo', 'tacit', 'tacky', 'talented', 'talkative', 'tall', 'tame', 'tan', 'tangible', 'tangy', 'tart', 'tasteful', 'tasteless', 'tasty', 'tattered', 'taut', 'tawdry', 'tearful', 'tedious', 'teeming', 'teeny', 'teeny-tiny', 'telling', 'temporary', 'tempting', 'ten', 'tender', 'tense', 'tenuous', 'tepid', 'terrible', 'terrific', 'tested', 'testy', 'thankful', 'that', 'therapeutic', 'these', 'thick', 'thin', 'thinkable', 'third', 'thirsty', 'this', 'thorny', 'thorough', 'those', 'thoughtful', 'thoughtless', 'threadbare', 'threatening', 'three', 'thrifty', 'thundering', 'thunderous', 'tidy', 'tight', 'tightfisted', 'timely', 'tinted', 'tiny', 'tired', 'tiresome', 'toothsome', 'torn', 'torpid', 'total', 'tough', 'towering', 'tragic', 'trained', 'tranquil', 'trashy', 'traumatic', 'treasured', 'tremendous', 'triangular', 'tricky', 'trifling', 'trim', 'trite', 'trivial', 'troubled', 'truculent', 'true', 'trusting', 'trustworthy', 'trusty', 'truthful', 'tubby', 'turbulent', 'twin', 'two', 'typical'], + 'u': + ['ubiquitous', 'ugliest', 'ugly', 'ultimate', 'ultra', 'unable', 'unaccountable', 'unarmed', 'unaware', 'unbecoming', 'unbiased', 'uncomfortable', 'uncommon', 'unconscious', 'uncovered', 'understated', 'understood', 'undesirable', 'unequal', 'unequaled', 'uneven', 'unfinished', 'unfit', 'unfolded', 'unfortunate', 'unhappy', 'unhealthy', 'uniform', 'unimportant', 'uninterested', 'unique', 'united', 'unkempt', 'unknown', 'unlawful', 'unlined', 'unlucky', 'unnatural', 'unpleasant', 'unrealistic', 'unripe', 'unruly', 'unselfish', 'unsightly', 'unsteady', 'unsuitable', 'unsung', 'untidy', 'untimely', 'untried', 'untrue', 'unused', 'unusual', 'unwelcome', 'unwieldy', 'unwitting', 'unwritten', 'upbeat', 'uppity', 'upright', 'upset', 'uptight', 'urban', 'usable', 'used', 'used', 'useful', 'useless', 'utilized', 'utopian', 'utter', 'uttermost'], + 'v': + ['vacant', 'vacuous', 'vagabond', 'vague', 'vain', 'valid', 'valuable', 'vapid', 'variable', 'various', 'vast', 'velvety', 'venerated', 'vengeful', 'venomous', 'verdant', 'verifiable', 'versed', 'vexed', 'vibrant', 'vicious', 'victorious', 'vigilant', 'vigorous', 'villainous', 'violent', 'violet', 'virtual', 'virtuous', 'visible', 'vital', 'vivacious', 'vivid', 'voiceless', 'volatile', 'voluminous', 'voracious', 'vulgar'], + 'w': + ['wacky', 'waggish', 'waiting', 'wakeful', 'wan', 'wandering', 'wanting', 'warlike', 'warm', 'warmhearted', 'warped', 'wary', 'wasteful', 'watchful', 'waterlogged', 'watery', 'wavy', 'weak', 'wealthy', 'weary', 'webbed', 'wee', 'weekly', 'weepy', 'weighty', 'weird', 'welcome', 'well-documented', 'well-groomed', 'well-informed', 'well-lit', 'well-made', 'well-off', 'well-to-do', 'well-worn', 'wet', 'which', 'whimsical', 'whirlwind', 'whispered', 'whispering', 'white', 'whole', 'wholesale', 'whopping', 'wicked', 'wide', 'wide-eyed', 'wiggly', 'wild', 'willing', 'wilted', 'winding', 'windy', 'winged', 'wiry', 'wise', 'wistful', 'witty', 'wobbly', 'woebegone', 'woeful', 'womanly', 'wonderful', 'wooden', 'woozy', 'wordy', 'workable', 'worldly', 'worn', 'worried', 'worrisome', 'worse', 'worst', 'worthless', 'worthwhile', 'worthy', 'wrathful', 'wretched', 'writhing', 'wrong', 'wry'], + 'x': + ['xenophobic'], + 'y': + ['yawning', 'yearly', 'yellow', 'yellowish', 'yielding', 'young', 'youthful', 'yummy'], + 'z': + ['zany', 'zealous', 'zesty', 'zigzag', 'zippy', 'zonked'] + }.freeze + SCIENTISTS = { + 'a': + ['Louis Agassiz', 'Maria Gaetana Agnesi', 'Al-Battani', 'Abu Nasr Al-Farabi', 'Jim Al-Khalili', 'Muhammad ibn Musa al-Khwarizmi', 'Mihailo Petrovic Alas', 'Angel Alcala', 'Salim Ali', 'Luis Alvarez', 'Andre Marie Ampère', 'Anaximander', 'Mary Anning', 'Virginia Apgar', 'Archimedes', 'Agnes Arber', 'Aristarchus', 'Aristotle', 'Svante Arrhenius', 'Oswald Avery', 'Amedeo Avogadro', 'Avicenna'], + 'b': + ['Charles Babbage', 'Francis Bacon', 'Alexander Bain', 'John Logie Baird', 'Joseph Banks', 'Ramon Barba', 'John Bardeen', 'Ibn Battuta', 'William Bayliss', 'George Beadle', 'Arnold Orville Beckman', 'Henri Becquerel', 'Emil Adolf Behring', 'Alexander Graham Bell', 'Emile Berliner', 'Claude Bernard', 'Timothy John Berners-Lee', 'Daniel Bernoulli', 'Jacob Berzelius', 'Henry Bessemer', 'Hans Bethe', 'Homi Jehangir Bhabha', 'Alfred Binet', 'Clarence Birdseye', 'Kristian Birkeland', 'Elizabeth Blackwell', 'Alfred Blalock', 'Katharine Burr Blodgett', 'Franz Boas', 'David Bohm', 'Aage Bohr', 'Niels Bohr', 'Ludwig Boltzmann', 'Max Born', 'Carl Bosch', 'Robert Bosch', 'Jagadish Chandra Bose', 'Satyendra Nath Bose', 'Walther Wilhelm Georg Bothe', 'Robert Boyle', 'Lawrence Bragg', 'Tycho Brahe', 'Brahmagupta', 'Georg Brandt', 'Wernher Von Braun', 'Louis de Broglie', 'Alexander Brongniart', 'Robert Brown', 'Michael E. Brown', 'Lester R. Brown', 'Eduard Buchner', 'William Buckland', 'Georges-Louis Leclerc, Comte de Buffon', 'Robert Bunsen', 'Luther Burbank', 'Jocelyn Bell Burnell', 'Thomas Burnet'], + 'c': + ['Benjamin Cabrera', 'Santiago Ramon y Cajal', 'Rachel Carson', 'George Washington Carver', 'Henry Cavendish', 'Anders Celsius', 'James Chadwick', 'Subrahmanyan Chandrasekhar', 'Erwin Chargaff', 'Noam Chomsky', 'Steven Chu', 'Leland Clark', 'Arthur Compton', 'Nicolaus Copernicus', 'Gerty Theresa Cori', 'Charles-Augustin de Coulomb', 'Jacques Cousteau', 'Brian Cox', 'Francis Crick', 'Nicholas Culpeper', 'Marie Curie', 'Pierre Curie', 'Georges Cuvier', 'Adalbert Czerny'], + 'd': + ['Gottlieb Daimler', 'John Dalton', 'James Dwight Dana', 'Charles Darwin', 'Humphry Davy', 'Peter Debye', 'Max Delbruck', 'Jean Andre Deluc', 'René Descartes', 'Rudolf Christian Karl Diesel', 'Paul Dirac', 'Prokop Divis', 'Theodosius Dobzhansky', 'Frank Drake', 'K. Eric Drexler'], + 'e': + ['Arthur Eddington', 'Thomas Edison', 'Paul Ehrlich', 'Albert Einstein', 'Gertrude Elion', 'Empedocles', 'Eratosthenes', 'Euclid', 'Leonhard Euler'], + 'f': + ['Michael Faraday', 'Pierre de Fermat', 'Enrico Fermi', 'Richard Feynman', 'Fibonacci – Leonardo of Pisa', 'Emil Fischer', 'Ronald Fisher', 'Alexander Fleming', 'Henry Ford', 'Lee De Forest', 'Dian Fossey', 'Leon Foucault', 'Benjamin Franklin', 'Rosalind Franklin', 'Sigmund Freud'], + 'g': + ['Galen', 'Galileo Galilei', 'Francis Galton', 'Luigi Galvani', 'George Gamow', 'Carl Friedrich Gauss', 'Murray Gell-Mann', 'Sophie Germain', 'Willard Gibbs', 'William Gilbert', 'Sheldon Lee Glashow', 'Robert Goddard', 'Maria Goeppert-Mayer', 'Jane Goodall', 'Stephen Jay Gould'], + 'h': + ['Fritz Haber', 'Ernst Haeckel', 'Otto Hahn', 'Albrecht von Haller', 'Edmund Halley', 'Thomas Harriot', 'William Harvey', 'Stephen Hawking', 'Otto Haxel', 'Werner Heisenberg', 'Hermann von Helmholtz', 'Jan Baptist von Helmont', 'Joseph Henry', 'William Herschel', 'Gustav Ludwig Hertz', 'Heinrich Hertz', 'Karl F. Herzfeld', 'Antony Hewish', 'David Hilbert', 'Maurice Hilleman', 'Hipparchus', 'Hippocrates', 'Shintaro Hirase', 'Dorothy Hodgkin', 'Robert Hooke', 'Frederick Gowland Hopkins', 'William Hopkins', 'Grace Murray Hopper', 'Frank Hornby', 'Jack Horner', 'Bernardo Houssay', 'Fred Hoyle', 'Edwin Hubble', 'Alexander von Humboldt', 'Zora Neale Hurston', 'James Hutton', 'Christiaan Huygens'], + 'i': + ['Ernesto Illy', 'Ernst Ising', 'Keisuke Ito'], + 'j': + ['Mae Carol Jemison', 'Edward Jenner', 'J. Hans D. Jensen', 'Irene Joliot-Curie', 'James Prescott Joule', 'Percy Lavon Julian'], + 'k': + ['Michio Kaku', 'Heike Kamerlingh Onnes', 'Friedrich August Kekulé', 'Frances Kelsey', 'Pearl Kendrick', 'Johannes Kepler', 'Abdul Qadeer Khan', 'Omar Khayyam', 'Alfred Kinsey', 'Gustav Kirchoff', 'Robert Koch', 'Emil Kraepelin', 'Thomas Kuhn', 'Stephanie Kwolek'], + 'l': + ['Jean-Baptiste Lamarck', 'Hedy Lamarr', 'Edwin Herbert Land', 'Karl Landsteiner', 'Pierre-Simon Laplace', 'Max von Laue', 'Antoine Lavoisier', 'Ernest Lawrence', 'Henrietta Leavitt', 'Antonie van Leeuwenhoek', 'Inge Lehmann', 'Gottfried Leibniz', 'Georges Lemaître', 'Leonardo da Vinci', 'Niccolo Leoniceno', 'Aldo Leopold', 'Rita Levi-Montalcini', 'Claude Levi-Strauss', 'Willard Frank Libby', 'Justus von Liebig', 'Carolus Linnaeus', 'Joseph Lister', 'John Locke', 'Hendrik Antoon Lorentz', 'Konrad Lorenz', 'Ada Lovelace', 'Lucretius', 'Charles Lyell', 'Trofim Lysenko'], + 'm': + ['Ernst Mach', 'Marcello Malpighi', 'Jane Marcet', 'Guglielmo Marconi', 'Lynn Margulis', 'James Clerk Maxwell', 'Ernst Mayr', 'Barbara McClintock', 'Lise Meitner', 'Gregor Mendel', 'Dmitri Mendeleev', 'Franz Mesmer', 'Antonio Meucci', 'Albert Abraham Michelson', 'Thomas Midgeley Jr.', 'Maria Mitchell', 'Mario Molina', 'Thomas Hunt Morgan', 'Henry Moseley'], + 'n': + ['Ukichiro Nakaya', 'John Napier', 'John Needham', 'John von Neumann', 'Thomas Newcomen', 'Isaac Newton', 'Florence Nightingale', 'Tim Noakes', 'Alfred Nobel', 'Emmy Noether', 'Christiane Nusslein-Volhard', 'Bill Nye'], + 'o': + ['Hans Christian Oersted', 'Georg Ohm', 'J. Robert Oppenheimer', 'Wilhelm Ostwald'], + 'p': + ['Blaise Pascal', 'Louis Pasteur', 'Wolfgang Ernst Pauli', 'Linus Pauling', 'Randy Pausch', 'Ivan Pavlov', 'Marguerite Perey', 'Jean Piaget', 'Philippe Pinel', 'Max Planck', 'Pliny the Elder', 'Karl Popper', 'Beatrix Potter', 'Joseph Priestley', 'Claudius Ptolemy', 'Pythagoras'], + 'q': + ['Harriet Quimby', 'Thabit ibn Qurra'], + 'r': + ['C. V. Raman', 'Srinivasa Ramanujan', 'William Ramsay', 'John Ray', 'Prafulla Chandra Ray', 'Francesco Redi', 'Sally Ride', 'Bernhard Riemann', 'Wilhelm Röntgen', 'Hermann Rorschach', 'Ronald Ross', 'Ibn Rushd', 'Ernest Rutherford'], + 's': + ['Carl Sagan', 'Mohammad Abdus Salam', 'Jonas Salk', 'Frederick Sanger', 'Alberto Santos-Dumont', 'Walter Schottky', 'Erwin Schrödinger', 'Theodor Schwann', 'Glenn Seaborg', 'Hans Selye', 'Charles Sherrington', 'Gene Shoemaker', 'Ernst Werner von Siemens', 'George Gaylord Simpson', 'B. F. Skinner', 'William Smith', 'Frederick Soddy', 'Arnold Sommerfeld', 'Nettie Stevens', 'William John Swainson', 'Leo Szilard'], + 't': + ['Niccolo Tartaglia', 'Edward Teller', 'Nikola Tesla', 'Thales of Miletus', 'Benjamin Thompson', 'J. J. Thomson', 'William Thomson', 'Henry David Thoreau', 'Kip S. Thorne', 'Clyde Tombaugh', 'Evangelista Torricelli', 'Charles Townes', 'Alan Turing', 'Neil deGrasse Tyson'], + 'u': + ['Harold Urey'], + 'v': + ['Craig Venter', 'Vladimir Vernadsky', 'Andreas Vesalius', 'Rudolf Virchow', 'Artturi Virtanen', 'Alessandro Volta'], + 'w': + ['George Wald', 'Alfred Russel Wallace', 'James Watson', 'James Watt', 'Alfred Wegener', 'John Archibald Wheeler', 'Maurice Wilkins', 'Thomas Willis', 'E. O. Wilson', 'Sven Wingqvist', 'Sergei Winogradsky', 'Friedrich Wöhler', 'Wilbur and Orville Wright', 'Wilhelm Wundt'], + 'x': + [], + 'y': + ['Chen-Ning Yang'], + 'z': + ['Ahmed Zewail'] + }.freeze + + desc 'Generate a new release name' + task generate_release_name: :environment do + def rand_el(arr) + arr[rand(arr.count)] + end + + puts '------------------------------------' + puts '' + puts 'sciNote release name generator v0.1 ALPHA' + puts '' + puts '------------------------------------' + + puts '' + puts 'Choose what you would like to do:' + puts '1) Provide a scientist by yourself' + puts '2) Randomly choose a scientist from a pre-defined list' + res = $stdin.gets.strip + unless res.in?(['', '1', '2']) + puts 'Invalid parameter, exiting' + next + end + + # First, pick scientist name + if res.in?(['', '1']) + puts 'Enter full scientist first name (all but surname) ' \ + 'in capitalized case' + first_name = $stdin.gets.strip + puts 'Enter full scientist surname ' \ + 'in capitalized case' + last_name = $stdin.gets.strip + key = last_name[0].downcase.to_sym + full_name = "#{first_name} #{last_name}" + else + key = rand_el(SCIENTISTS.keys) + full_name = rand_el(SCIENTISTS[key]) + last_name = full_name.split(' ')[-1] + puts "Randomly chosen scientist: #{full_name}" + puts '' + end + + # Now, pick adjective + adjective = rand_el(ADJECTIVES[key]) + + puts '------------------------------------' + puts 'Tadaaaa!' + puts 'The new release will be named......' + puts '(waaaaait for iiiiit)' + puts '' + puts '##############################################' + puts " #{adjective.capitalize} #{last_name}" + puts " (full name: #{full_name})" + puts '##############################################' + + loop do + puts '' + puts 'What would you like to do?' + puts '(E) Exit' + puts '(a) generate new adjective' + puts '(s) generate new random scientist' + res = $stdin.gets.strip + unless res.in?(['', 'e', 'E', 'a', 'A', 's', 'S']) + puts 'Invalid parameter!' + next + end + + break if res.in?(['', 'e', 'E']) + + if res.in?(%w(s S)) + key = rand_el(SCIENTISTS.keys) + full_name = rand_el(SCIENTISTS[key]) + last_name = full_name.split(' ')[-1] + end + + adjective = rand_el(ADJECTIVES[key]) + + puts '' + puts '##############################################' + puts " #{adjective.capitalize} #{last_name} " + puts " (full name: #{full_name})" + puts '##############################################' + end + end +end From 85634b2fb66d4c5b231f532a79454ff0573f921a Mon Sep 17 00:00:00 2001 From: Luka Murn Date: Mon, 7 Aug 2017 14:04:39 +0200 Subject: [PATCH 06/24] Add 'off' before setting export button to 'on' --- app/assets/javascripts/repositories/repository_datatable.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/repositories/repository_datatable.js b/app/assets/javascripts/repositories/repository_datatable.js index f868deffb..4e9225a92 100644 --- a/app/assets/javascripts/repositories/repository_datatable.js +++ b/app/assets/javascripts/repositories/repository_datatable.js @@ -734,10 +734,10 @@ var RepositoryDatatable = (function(global) { if (!events || !events.click) { $('#exportRepositoriesButton').removeClass('disabled'); $('#exportRepositoriesButton').prop('disabled', false); - $('#exportRepositoriesButton').on('click', function() { + $('#exportRepositoriesButton').off('click').on('click', function() { $('#exportRepositoryModal').modal('show'); }); - $('#export-repositories').on('click', function() { + $('#export-repositories').off('click').on('click', function() { animateSpinner(null, true); $('#form-export').submit(); }); From c62002381b18e1cb3783857eecab5885b448f83d Mon Sep 17 00:00:00 2001 From: Luka Murn Date: Thu, 10 Aug 2017 11:30:57 +0200 Subject: [PATCH 07/24] Add default settings migration and concern --- app/controllers/application_controller.rb | 2 +- .../account/preferences_controller.rb | 2 +- app/models/concerns/settings_model.rb | 22 ++++++++ app/models/user.rb | 15 ++++- app/serializers/jsonb_hash_serializer.rb | 11 ++++ .../account/preferences/index.html.erb | 8 +-- .../20170809131000_refactor_user_settings.rb | 53 ++++++++++++++++++ scinote-web-v1.0.0.tgz | Bin 0 -> 23258 bytes spec/models/user_spec.rb | 9 +-- 9 files changed, 107 insertions(+), 15 deletions(-) create mode 100644 app/models/concerns/settings_model.rb create mode 100644 app/serializers/jsonb_hash_serializer.rb create mode 100644 db/migrate/20170809131000_refactor_user_settings.rb create mode 100644 scinote-web-v1.0.0.tgz diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index e0e50c25b..678f4b7aa 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -87,6 +87,6 @@ class ApplicationController < ActionController::Base end def set_time_zone(&block) - Time.use_zone(current_user.time_zone, &block) + Time.use_zone(current_user.settings[:time_zone], &block) end end diff --git a/app/controllers/users/settings/account/preferences_controller.rb b/app/controllers/users/settings/account/preferences_controller.rb index ac85f0148..b096bfa1b 100644 --- a/app/controllers/users/settings/account/preferences_controller.rb +++ b/app/controllers/users/settings/account/preferences_controller.rb @@ -115,7 +115,7 @@ module Users def update_params params.require(:user).permit( - :time_zone + settings: :time_zone ) end end diff --git a/app/models/concerns/settings_model.rb b/app/models/concerns/settings_model.rb new file mode 100644 index 000000000..c74425422 --- /dev/null +++ b/app/models/concerns/settings_model.rb @@ -0,0 +1,22 @@ +module SettingsModel + extend ActiveSupport::Concern + + @@default_settings = HashWithIndifferentAccess.new + + included do + serialize :settings, JsonbHashSerializer + after_initialize :init_default_settings, if: :new_record? + end + + class_methods do + def default_settings(dfs) + @@default_settings.merge!(dfs) + end + end + + protected + + def init_default_settings + self.settings = @@default_settings + end +end diff --git a/app/models/user.rb b/app/models/user.rb index c7c5fb3dd..bceb665a2 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,5 +1,6 @@ class User < ApplicationRecord include SearchableModel + include SettingsModel acts_as_token_authenticatable devise :invitable, :confirmable, :database_authenticatable, :registerable, @@ -33,9 +34,19 @@ class User < ApplicationRecord validates_attachment :avatar, :content_type => { :content_type => ["image/jpeg", "image/png"] }, size: { less_than: Constants::AVATAR_MAX_SIZE_MB.megabytes } - validates :time_zone, presence: true validate :time_zone_check + default_settings( + time_zone: 'UTC', + notifications: { + assignments: true, + assignments_email: false, + recent: true, + recent_email: false, + system_message_email: false + } + ) + # Relations has_many :user_teams, inverse_of: :user has_many :teams, through: :user_teams @@ -384,7 +395,7 @@ class User < ApplicationRecord end def time_zone_check - if time_zone.nil? or ActiveSupport::TimeZone.new(time_zone).nil? + if settings[:time_zone].nil? or ActiveSupport::TimeZone.new(settings[:time_zone]).nil? errors.add(:time_zone) end end diff --git a/app/serializers/jsonb_hash_serializer.rb b/app/serializers/jsonb_hash_serializer.rb new file mode 100644 index 000000000..f01f29560 --- /dev/null +++ b/app/serializers/jsonb_hash_serializer.rb @@ -0,0 +1,11 @@ +class JsonbHashSerializer + def self.dump(hash) + hash.to_json + end + + def self.load(hash) + hash ||= {} + hash = JSON.parse(hash) if hash.instance_of? String + hash.with_indifferent_access + end +end diff --git a/app/views/users/settings/account/preferences/index.html.erb b/app/views/users/settings/account/preferences/index.html.erb index 18ed8eeae..0f06e94ce 100644 --- a/app/views/users/settings/account/preferences/index.html.erb +++ b/app/views/users/settings/account/preferences/index.html.erb @@ -12,7 +12,7 @@ <%= form_for(@user, url: update_preferences_path(format: :json), remote: true, - html: { method: :put, 'data-for' => 'time_zone' }) do |f| %> + html: { method: :put, 'data-for' => 'settings[time_zone]' }) do |f| %>
<%= f.label t("users.settings.account.preferences.edit.time_zone_label") %> @@ -21,9 +21,9 @@ disabled="disabled" autocomplete="off" type="text" - value="<%= @user.time_zone %>" - name="fake_user[time_zone]" - id="fake_user_time_zone"> + value="<%= @user.settings[:time_zone] %>" + name="fake_user[settings][time_zone]" + id="fake_user_settings_time_zone"> <%=t "general.edit" %> diff --git a/db/migrate/20170809131000_refactor_user_settings.rb b/db/migrate/20170809131000_refactor_user_settings.rb new file mode 100644 index 000000000..4dd54cf8d --- /dev/null +++ b/db/migrate/20170809131000_refactor_user_settings.rb @@ -0,0 +1,53 @@ +class RefactorUserSettings < ActiveRecord::Migration[5.1] + def up + add_column :users, :settings, :jsonb, default: {}, null: false + + User.find_each do |user| + settings = { + time_zone: user['time_zone'], + notifications: { + assignments: user['assignments_notification'], + assignments_email: user['assignments_notification_email'], + recent: user['recent_notification'], + recent_email: user['recent_notification_email'], + system_message_email: user['system_message_notification_email'] + } + } + user.update(settings: settings) + end + + remove_column :users, :time_zone, :string + remove_column :users, :assignments_notification, :boolean + remove_column :users, :assignments_notification_email, :boolean + remove_column :users, :recent_notification, :boolean + remove_column :users, :recent_notification_email, :boolean + remove_column :users, :system_message_notification_email, :boolean + end + + def down + add_column :users, :time_zone, :string, default: false + add_column :users, :assignments_notification, :boolean, default: false + add_column :users, :assignments_notification_email, :boolean, default: false + add_column :users, :recent_notification, :boolean, default: false + add_column :users, :recent_notification_email, :boolean, default: false + add_column :users, + :system_message_notification_email, :boolean, default: false + + User.find_each do |user| + user.time_zone = user.settings[:time_zone] + user.assignments_notification = + user.settings[:notifications][:assignments] + user.assignments_notification_email = + user.settings[:notifications][:assignments_email] + user.recent_notification = + user.settings[:notifications][:recent] + user.recent_notification_email = + user.settings[:notifications][:recent_email] + user.system_message_notification_email = + user.settings[:notifications][:system_message_email] + user.save + end + + remove_column :users, :settings, :jsonb + end +end diff --git a/scinote-web-v1.0.0.tgz b/scinote-web-v1.0.0.tgz new file mode 100644 index 0000000000000000000000000000000000000000..289870cc3256cd95766a2e77eddad30c733a856d GIT binary patch literal 23258 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

sCves%HyF`-(k`7CVG6B0cS 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 U^JzZK=RQCGKU)njX8>RV0NuAJ$^ZZW literal 0 HcmV?d00001 diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index aa55b0a06..b4c1515d7 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -28,7 +28,6 @@ describe User, type: :model do it { should have_db_column :confirmed_at } it { should have_db_column :confirmation_sent_at } it { should have_db_column :unconfirmed_email } - it { should have_db_column :time_zone } it { should have_db_column :invitation_token } it { should have_db_column :invitation_created_at } it { should have_db_column :invitation_sent_at } @@ -38,12 +37,8 @@ describe User, type: :model do it { should have_db_column :invited_by_type } it { should have_db_column :invitations_count } it { should have_db_column :tutorial_status } - it { should have_db_column :assignments_notification } - it { should have_db_column :recent_notification } - it { should have_db_column :assignments_notification_email } - it { should have_db_column :recent_notification_email } + it { should have_db_column :settings } it { should have_db_column :current_team_id } - it { should have_db_column :system_message_notification_email } it { should have_db_column :authentication_token } end @@ -115,7 +110,7 @@ describe User, type: :model do it { should validate_presence_of :full_name } it { should validate_presence_of :initials } it { should validate_presence_of :email } - it { should validate_presence_of :time_zone } + it { should validate_presence_of :settings } it do should validate_length_of(:full_name).is_at_most( From 9227ea5854c380dc654de0f1eb6a176e69a73889 Mon Sep 17 00:00:00 2001 From: Luka Murn Date: Thu, 10 Aug 2017 14:29:01 +0200 Subject: [PATCH 08/24] Finish the user settings jsonb, also fix references throughout app Closes SCI-1475. --- .../users/invitations_controller.rb | 2 +- .../settings/account/preferences_controller.rb | 12 ++++++------ app/helpers/application_helper.rb | 2 +- app/helpers/notifications_helper.rb | 2 +- app/models/activity.rb | 4 ++-- app/models/user.rb | 2 ++ app/models/user_notification.rb | 6 +++--- .../account/preferences/index.html.erb | 18 +++++++++++------- 8 files changed, 27 insertions(+), 21 deletions(-) diff --git a/app/controllers/users/invitations_controller.rb b/app/controllers/users/invitations_controller.rb index bd199cd7a..2e34622bc 100644 --- a/app/controllers/users/invitations_controller.rb +++ b/app/controllers/users/invitations_controller.rb @@ -180,7 +180,7 @@ module Users message: sanitize_input(message) ) - if target_user.assignments_notification + if target_user.settings[:notifications][:assignments] UserNotification.create(notification: notification, user: target_user) end end diff --git a/app/controllers/users/settings/account/preferences_controller.rb b/app/controllers/users/settings/account/preferences_controller.rb index b096bfa1b..4cfc94463 100644 --- a/app/controllers/users/settings/account/preferences_controller.rb +++ b/app/controllers/users/settings/account/preferences_controller.rb @@ -77,15 +77,15 @@ module Users end def notifications_settings - @user.assignments_notification = + @user.settings[:notifications][:assignments] = params[:assignments_notification] ? true : false - @user.recent_notification = + @user.settings[:notifications][:recent] = params[:recent_notification] ? true : false - @user.recent_notification_email = + @user.settings[:notifications][:recent_email] = params[:recent_notification_email] ? true : false - @user.assignments_notification_email = + @user.settings[:notifications][:assignments_email] = params[:assignments_notification_email] ? true : false - @user.system_message_notification_email = + @user.settings[:notifications][:system_message_email] = params[:system_message_notification_email] ? true : false if @user.save @@ -115,7 +115,7 @@ module Users def update_params params.require(:user).permit( - settings: :time_zone + :time_zone ) end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 501fa65ac..1713b706c 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -100,7 +100,7 @@ module ApplicationHelper title: sanitize_input(title), message: sanitize_input(message) ) - if target_user.assignments_notification + if target_user.settings[:notifications][:assignments] UserNotification.create(notification: notification, user: target_user) end end diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb index f41eb90ac..248fd5b11 100644 --- a/app/helpers/notifications_helper.rb +++ b/app/helpers/notifications_helper.rb @@ -44,7 +44,7 @@ module NotificationsHelper message: sanitize_input(message) ) - if target_user.assignments_notification + if target_user.settings[:notifications][:assignments] UserNotification.create(notification: notification, user: target_user) end end diff --git a/app/models/activity.rb b/app/models/activity.rb index e4dd2d029..ea4eaa90a 100644 --- a/app/models/activity.rb +++ b/app/models/activity.rb @@ -118,9 +118,9 @@ class Activity < ApplicationRecord project.users.each do |project_user| next if project_user == user - next if !project_user.assignments_notification && + next if !project_user.settings[:notifications][:assignments] && notification.type_of == 'assignment' - next if !project_user.recent_notification && + next if !project_user.settings[:notifications][:recent] && notification.type_of == 'recent_changes' UserNotification.create(notification: notification, user: project_user) end diff --git a/app/models/user.rb b/app/models/user.rb index bceb665a2..886fc77f3 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -36,6 +36,8 @@ class User < ApplicationRecord size: { less_than: Constants::AVATAR_MAX_SIZE_MB.megabytes } validate :time_zone_check + store_accessor :settings, :time_zone + default_settings( time_zone: 'UTC', notifications: { diff --git a/app/models/user_notification.rb b/app/models/user_notification.rb index 98593e5d7..ba9e494e3 100644 --- a/app/models/user_notification.rb +++ b/app/models/user_notification.rb @@ -40,17 +40,17 @@ class UserNotification < ApplicationRecord send_email_notification( user, notification - ) if user.system_message_notification_email + ) if user.settings[:notifications][:system_message_email] when 'assignment' send_email_notification( user, notification - ) if user.assignments_notification_email + ) if user.settings[:notifications][:assignments_email] when 'recent_changes' send_email_notification( user, notification - ) if user.recent_notification_email + ) if user.settings[:notifications][:recent_email] when 'deliver' send_email_notification( user, diff --git a/app/views/users/settings/account/preferences/index.html.erb b/app/views/users/settings/account/preferences/index.html.erb index 0f06e94ce..e982e6522 100644 --- a/app/views/users/settings/account/preferences/index.html.erb +++ b/app/views/users/settings/account/preferences/index.html.erb @@ -12,7 +12,11 @@ <%= form_for(@user, url: update_preferences_path(format: :json), remote: true, - html: { method: :put, 'data-for' => 'settings[time_zone]' }) do |f| %> + html: { + method: :put, + 'data-for' => 'settings[time_zone]', + 'data-turbolinks' => false + }) do |f| %>

<%= f.label t("users.settings.account.preferences.edit.time_zone_label") %> @@ -35,7 +39,7 @@

<%=t "users.settings.account.preferences.edit.time_zone_title" %>

- <%= f.select :time_zone, ActiveSupport::TimeZone.all.collect { |tz| + <%= f.select :time_zone , ActiveSupport::TimeZone.all.collect { |tz| [tz.formatted_offset + " " + tz.name, tz.name] }, {}, {class: 'form-control selectpicker', 'ata-role' => 'clear'} %> <%= t("users.settings.account.preferences.edit.time_zone_sublabel") %> @@ -75,7 +79,7 @@ <%=t 'notifications.form.notification_scinote' %>
- <%= check_box_tag :assignments_notification, @user.assignments_notification %> + <%= check_box_tag :assignments_notification, @user.settings[:notifications][:assignments] %>
@@ -83,7 +87,7 @@ <%=t 'notifications.form.notification_email' %>
- <%= check_box_tag :assignments_notification_email, @user.assignments_notification_email %> + <%= check_box_tag :assignments_notification_email, @user.settings[:notifications][:assignments_email] %>
@@ -100,7 +104,7 @@ <%=t 'notifications.form.notification_scinote' %>
- <%= check_box_tag :recent_notification, @user.recent_notification %> + <%= check_box_tag :recent_notification, @user.settings[:notifications][:recent] %>
@@ -108,7 +112,7 @@ <%=t 'notifications.form.notification_email' %>
- <%= check_box_tag :recent_notification_email, @user.recent_notification_email %> + <%= check_box_tag :recent_notification_email, @user.settings[:notifications][:recent_email] %>
@@ -133,7 +137,7 @@ <%=t 'notifications.form.notification_email' %>
- <%= check_box_tag :system_message_notification_email, @user.system_message_notification_email %> + <%= check_box_tag :system_message_notification_email, @user.settings[:notifications][:system_message_email] %>
From ec7b7ffe0879a8e590547200830afcaebed16c8d Mon Sep 17 00:00:00 2001 From: Luka Murn Date: Thu, 10 Aug 2017 14:42:58 +0200 Subject: [PATCH 09/24] You are my sunshine, my only sunshine, You make me happy when skies are grey You never know, Hound, how much I love you Please don't take my Hound away --- app/models/user.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/models/user.rb b/app/models/user.rb index 886fc77f3..ec10c4b30 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -397,7 +397,8 @@ class User < ApplicationRecord end def time_zone_check - if settings[:time_zone].nil? or ActiveSupport::TimeZone.new(settings[:time_zone]).nil? + if time_zone.nil? || + ActiveSupport::TimeZone.new(time_zone).nil? errors.add(:time_zone) end end From 90188c89c935c08b7e4a2aa0a578a2c999079f63 Mon Sep 17 00:00:00 2001 From: Luka Murn Date: Tue, 22 Aug 2017 08:34:58 +0200 Subject: [PATCH 10/24] Update delayed_paperclip library Closes SCI-1376. --- Gemfile | 4 +++- Gemfile.lock | 14 ++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Gemfile b/Gemfile index 0a074d9f9..f085065ba 100644 --- a/Gemfile +++ b/Gemfile @@ -57,7 +57,9 @@ gem 'deface', '~> 1.0' gem 'nokogiri' # HTML/XML parser gem 'sneaky-save', git: 'https://github.com/einzige/sneaky-save' gem 'rails_autolink', '~> 1.1', '>= 1.1.6' -gem 'delayed_paperclip' +gem 'delayed_paperclip', + git: 'https://github.com/jrgifford/delayed_paperclip.git', + ref: 'fcf574c' gem 'rubyzip' gem 'activerecord-import' diff --git a/Gemfile.lock b/Gemfile.lock index aeeb3b107..13f236397 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -5,6 +5,15 @@ GIT sneaky-save (0.1.2) activerecord (>= 3.2.0) +GIT + remote: https://github.com/jrgifford/delayed_paperclip.git + revision: fcf574c1188213d3c8fce934fd52861a8ba080cb + ref: fcf574c + specs: + delayed_paperclip (3.0.1) + activejob (>= 4.2) + paperclip (>= 3.3) + GEM remote: http://rubygems.org/ specs: @@ -117,9 +126,6 @@ GEM delayed_job_active_record (4.1.0) activerecord (>= 3.0, < 5) delayed_job (>= 3.0, < 5) - delayed_paperclip (3.0.1) - activejob (>= 4.2) - paperclip (>= 3.3) devise (3.5.6) bcrypt (~> 3.0) orm_adapter (~> 0.1) @@ -360,7 +366,7 @@ DEPENDENCIES commit_param_routing deface (~> 1.0) delayed_job_active_record - delayed_paperclip + delayed_paperclip! devise (= 3.5.6) devise-async devise_invitable From 5ee7fd895ccfb54f940fb45d85b0275053acfa1f Mon Sep 17 00:00:00 2001 From: Luka Murn Date: Wed, 23 Aug 2017 08:35:48 +0200 Subject: [PATCH 11/24] Moved the arrays into json --- lib/tasks/versions.rake | 193 ------------------ lib/tasks/versions/adjectives.json | 54 +++++ lib/tasks/versions/generate_release_name.rake | 88 ++++++++ lib/tasks/versions/scientists.json | 54 +++++ 4 files changed, 196 insertions(+), 193 deletions(-) delete mode 100644 lib/tasks/versions.rake create mode 100644 lib/tasks/versions/adjectives.json create mode 100644 lib/tasks/versions/generate_release_name.rake create mode 100644 lib/tasks/versions/scientists.json diff --git a/lib/tasks/versions.rake b/lib/tasks/versions.rake deleted file mode 100644 index d3d9ffa60..000000000 --- a/lib/tasks/versions.rake +++ /dev/null @@ -1,193 +0,0 @@ -namespace :versions do - ADJECTIVES = { - 'a': - ['aback', 'abaft', 'abandoned', 'abashed', 'aberrant', 'abhorrent', 'abiding', 'abject', 'ablaze', 'able', 'abnormal', 'aboard', 'aboriginal', 'abortive', 'abounding', 'abrasive', 'abrupt', 'absent', 'absolute', 'absorbed', 'absorbing', 'abstracted', 'absurd', 'abundant', 'abusive', 'academic', 'acceptable', 'accessible', 'accidental', 'acclaimed', 'accomplished', 'accurate', 'aching', 'acid', 'acidic', 'acoustic', 'acrid', 'acrobatic', 'active', 'actual', 'actually', 'ad hoc', 'adamant', 'adaptable', 'addicted', 'adept', 'adhesive', 'adjoining', 'admirable', 'admired', 'adolescent', 'adorable', 'adored', 'advanced', 'adventurous', 'affectionate', 'afraid', 'aged', 'aggravating', 'aggressive', 'agile', 'agitated', 'agonizing', 'agreeable', 'ahead', 'ajar', 'alarmed', 'alarming', 'alcoholic', 'alert', 'alienated', 'alike', 'alive', 'all', 'alleged', 'alluring', 'aloof', 'altruistic', 'amazing', 'ambiguous', 'ambitious', 'amiable', 'ample', 'amuck', 'amused', 'amusing', 'anchored', 'ancient', 'ancient', 'angelic', 'angry', 'angry', 'anguished', 'animated', 'annoyed', 'annoying', 'annual', 'another', 'antique', 'antsy', 'anxious', 'any', 'apathetic', 'appetizing', 'apprehensive', 'appropriate', 'apt', 'aquatic', 'arctic', 'arid', 'aromatic', 'arrogant', 'artistic', 'ashamed', 'aspiring', 'assorted', 'assured', 'astonishing', 'athletic', 'attached', 'attentive', 'attractive', 'auspicious', 'austere', 'authentic', 'authorized', 'automatic', 'available', 'avaricious', 'average', 'awake', 'aware', 'awesome', 'awful', 'awkward', 'axiomatic'], - 'b': - ['babyish', 'back', 'bad', 'baggy', 'barbarous', 'bare', 'barren', 'bashful', 'basic', 'batty', 'bawdy', 'beautiful', 'beefy', 'befitting', 'belated', 'belligerent', 'beloved', 'beneficial', 'bent', 'berserk', 'best', 'better', 'bewildered', 'bewitched', 'big', 'big-hearted', 'billowy', 'biodegradable', 'bite-sized', 'biting', 'bitter', 'bizarre', 'black', 'black-and-white', 'bland', 'blank', 'blaring', 'bleak', 'blind', 'blissful', 'blond', 'bloody', 'blue', 'blue-eyed', 'blushing', 'bogus', 'boiling', 'bold', 'bony', 'boorish', 'bored', 'boring', 'bossy', 'both', 'bouncy', 'boundless', 'bountiful', 'bowed', 'brainy', 'brash', 'brave', 'brawny', 'breakable', 'breezy', 'brief', 'bright', 'brilliant', 'brisk', 'broad', 'broken', 'bronze', 'brown', 'bruised', 'bubbly', 'bulky', 'bumpy', 'buoyant', 'burdensome', 'burly', 'bustling', 'busy', 'buttery', 'buzzing'], - 'c': - ['cagey', 'calculating', 'callous', 'calm', 'candid', 'canine', 'capable', 'capital', 'capricious', 'carefree', 'careful', 'careless', 'caring', 'cautious', 'cavernous', 'ceaseless', 'celebrated', 'certain', 'changeable', 'charming', 'cheap', 'cheeky', 'cheerful', 'cheery', 'chemical', 'chief', 'childlike', 'chilly', 'chivalrous', 'chubby', 'chunky', 'circular', 'clammy', 'classic', 'classy', 'clean', 'clear', 'clear-cut', 'clever', 'cloistered', 'close', 'closed', 'cloudy', 'clueless', 'clumsy', 'cluttered', 'coarse', 'coherent', 'cold', 'colorful', 'colorless', 'colossal', 'colossal', 'combative', 'comfortable', 'common', 'compassionate', 'competent', 'complete', 'complex', 'complicated', 'composed', 'concerned', 'concrete', 'condemned', 'condescending', 'confused', 'conscious', 'considerate', 'constant', 'contemplative', 'content', 'conventional', 'convincing', 'convoluted', 'cooing', 'cooked', 'cool', 'cooperative', 'coordinated', 'corny', 'corrupt', 'costly', 'courageous', 'courteous', 'cowardly', 'crabby', 'crafty', 'craven', 'crazy', 'creamy', 'creative', 'creepy', 'criminal', 'crisp', 'critical', 'crooked', 'crowded', 'cruel', 'crushing', 'cuddly', 'cultivated', 'cultured', 'cumbersome', 'curious', 'curly', 'curved', 'curvy', 'cut', 'cute', 'cylindrical', 'cynical'], - 'd': - ['daffy', 'daily', 'damaged', 'damaging', 'damp', 'dangerous', 'dapper', 'dapper', 'daring', 'dark', 'darling', 'dashing', 'dazzling', 'dead', 'deadly', 'deadpan', 'deafening', 'dear', 'dearest', 'debonair', 'decayed', 'deceitful', 'decent', 'decimal', 'decisive', 'decorous', 'deep', 'deeply', 'defeated', 'defective', 'defenseless', 'defensive', 'defiant', 'deficient', 'definite', 'delayed', 'delectable', 'delicate', 'delicious', 'delightful', 'delirious', 'demanding', 'demonic', 'dense', 'dental', 'dependable', 'dependent', 'depraved', 'depressed', 'deranged', 'descriptive', 'deserted', 'despicable', 'detailed', 'determined', 'devilish', 'devoted', 'didactic', 'different', 'difficult', 'digital', 'dilapidated', 'diligent', 'dim', 'diminutive', 'dimpled', 'dimwitted', 'direct', 'direful', 'dirty', 'disagreeable', 'disastrous', 'discreet', 'discrete', 'disfigured', 'disguised', 'disgusted', 'disgusting', 'dishonest', 'disillusioned', 'disloyal', 'dismal', 'dispensable', 'distant', 'distinct', 'distorted', 'distraught', 'distressed', 'disturbed', 'divergent', 'dizzy', 'domineering', 'dopey', 'doting', 'double', 'doubtful', 'downright', 'drab', 'draconian', 'drafty', 'drained', 'dramatic', 'dreary', 'droopy', 'drunk', 'dry', 'dual', 'dull', 'dull', 'dusty', 'dutiful', 'dynamic', 'dysfunctional'], - 'e': - ['each', 'eager', 'early', 'earnest', 'earsplitting', 'earthy', 'easy', 'easy-going', 'eatable', 'economic', 'ecstatic', 'edible', 'educated', 'efficacious', 'efficient', 'eight', 'elaborate', 'elastic', 'elated', 'elderly', 'electric', 'elegant', 'elementary', 'elfin', 'elite', 'elliptical', 'emaciated', 'embarrassed', 'embellished', 'eminent', 'emotional', 'empty', 'enchanted', 'enchanting', 'encouraging', 'endurable', 'energetic', 'enlightened', 'enormous', 'enraged', 'entertaining', 'enthusiastic', 'entire', 'envious', 'envious', 'equable', 'equal', 'equatorial', 'erect', 'erratic', 'essential', 'esteemed', 'ethereal', 'ethical', 'euphoric', 'evanescent', 'evasive', 'even', 'evergreen', 'everlasting', 'every', 'evil', 'exalted', 'exasperated', 'excellent', 'excitable', 'excited', 'exciting', 'exclusive', 'exemplary', 'exhausted', 'exhilarated', 'exotic', 'expensive', 'experienced', 'expert', 'extensive', 'extra-large', 'extraneous', 'extra-small', 'extroverted', 'exuberant', 'exultant'], - 'f': - ['fabulous', 'faded', 'failing', 'faint', 'fair', 'faithful', 'fake', 'fallacious', 'false', 'familiar', 'famous', 'fanatical', 'fancy', 'fantastic', 'far', 'faraway', 'far-flung', 'far-off', 'fascinated', 'fast', 'fat', 'fatal', 'fatherly', 'faulty', 'favorable', 'favorite', 'fearful', 'fearless', 'feeble', 'feigned', 'feisty', 'feline', 'female', 'feminine', 'fertile', 'festive', 'few', 'fickle', 'fierce', 'filthy', 'fine', 'finicky', 'finished', 'firm', 'first', 'firsthand', 'fitting', 'five', 'fixed', 'flagrant', 'flaky', 'flamboyant', 'flashy', 'flat', 'flawed', 'flawless', 'flickering', 'flimsy', 'flippant', 'floppy', 'flowery', 'flufy', 'fluid', 'flustered', 'fluttering', 'foamy', 'focused', 'fond', 'foolhardy', 'foolish', 'forceful', 'foregoing', 'forgetful', 'forked', 'formal', 'forsaken', 'forthright', 'fortunate', 'four', 'fragile', 'fragrant', 'frail', 'frank', 'frantic', 'frayed', 'free', 'freezing', 'French', 'frequent', 'fresh', 'fretful', 'friendly', 'frightened', 'frightening', 'frigid', 'frilly', 'frivolous', 'frizzy', 'front', 'frosty', 'frothy', 'frozen', 'frugal', 'fruitful', 'frustrating', 'full', 'fumbling', 'fumbling', 'functional', 'funny', 'furry', 'furtive', 'fussy', 'future', 'futuristic', 'fuzzy'], - 'g': - ['gabby', 'gainful', 'gamy', 'gaping', 'gargantuan', 'garrulous', 'gaseous', 'gaudy', 'general', 'general', 'generous', 'gentle', 'genuine', 'ghastly', 'giant', 'giddy', 'gifted', 'gigantic', 'giving', 'glamorous', 'glaring', 'glass', 'gleaming', 'gleeful', 'glib', 'glistening', 'glittering', 'gloomy', 'glorious', 'glossy', 'glum', 'godly', 'golden', 'good', 'good-natured', 'goofy', 'gorgeous', 'graceful', 'gracious', 'grand', 'grandiose', 'grandiose', 'granular', 'grateful', 'gratis', 'grave', 'gray', 'greasy', 'great', 'greedy', 'green', 'gregarious', 'grey', 'grieving', 'grim', 'grimy', 'gripping', 'grizzled', 'groovy', 'gross', 'grotesque', 'grouchy', 'grounded', 'growing', 'growling', 'grown', 'grubby', 'gruesome', 'grumpy', 'guarded', 'guiltless', 'guilty', 'gullible', 'gummy', 'gusty', 'guttural'], - 'h': - ['habitual', 'hairy', 'half', 'half', 'hallowed', 'halting', 'handmade', 'handsome', 'handsomely', 'handy', 'hanging', 'hapless', 'happy', 'happy-go-lucky', 'hard', 'hard-to-find', 'harebrained', 'harmful', 'harmless', 'harmonious', 'harsh', 'hasty', 'hateful', 'haunting', 'heady', 'healthy', 'heartbreaking', 'heartfelt', 'hearty', 'heavenly', 'heavy', 'hefty', 'hellish', 'helpful', 'helpless', 'hesitant', 'hidden', 'hideous', 'high', 'highfalutin', 'high-level', 'high-pitched', 'hilarious', 'hissing', 'historical', 'hoarse', 'holistic', 'hollow', 'homeless', 'homely', 'honest', 'honorable', 'honored', 'hopeful', 'horrible', 'horrific', 'hospitable', 'hot', 'huge', 'hulking', 'humble', 'humdrum', 'humiliating', 'humming', 'humongous', 'humorous', 'hungry', 'hurried', 'hurt', 'hurtful', 'hushed', 'husky', 'hypnotic', 'hysterical'], - 'i': - ['icky', 'icy', 'ideal', 'ideal', 'idealistic', 'identical', 'idiotic', 'idle', 'idolized', 'ignorant', 'ill', 'illegal', 'ill-fated', 'ill-informed', 'illiterate', 'illustrious', 'imaginary', 'imaginative', 'immaculate', 'immaterial', 'immediate', 'immense', 'imminent', 'impartial', 'impassioned', 'impeccable', 'imperfect', 'imperturbable', 'impish', 'impolite', 'important', 'imported', 'impossible', 'impractical', 'impressionable', 'impressive', 'improbable', 'impure', 'inborn', 'incandescent', 'incomparable', 'incompatible', 'incompetent', 'incomplete', 'inconclusive', 'inconsequential', 'incredible', 'indelible', 'indolent', 'industrious', 'inexpensive', 'inexperienced', 'infamous', 'infantile', 'infatuated', 'inferior', 'infinite', 'informal', 'innate', 'innocent', 'inquisitive', 'insecure', 'insidious', 'insignificant', 'insistent', 'instinctive', 'instructive', 'insubstantial', 'intelligent', 'intent', 'intentional', 'interesting', 'internal', 'international', 'intrepid', 'intrigued', 'invincible', 'irate', 'ironclad', 'irresponsible', 'irritable', 'irritating', 'itchy'], - 'j': - ['jaded', 'jagged', 'jam-packed', 'jaunty', 'jazzy', 'jealous', 'jittery', 'jobless', 'joint', 'jolly', 'jovial', 'joyful', 'joyous', 'jubilant', 'judicious', 'juicy', 'jumbled', 'jumbo', 'jumpy', 'jumpy', 'junior', 'juvenile'], - 'k': - ['kaleidoscopic', 'kaput', 'keen', 'key', 'kind', 'kindhearted', 'kindly', 'klutzy', 'knobby', 'knotty', 'knowing', 'knowledgeable', 'known', 'kooky', 'kosher'], - 'l': - ['labored', 'lackadaisical', 'lacking', 'lame', 'lame', 'lamentable', 'languid', 'lanky', 'large', 'last', 'lasting', 'late', 'laughable', 'lavish', 'lawful', 'lazy', 'leading', 'leafy', 'lean', 'learned', 'left', 'legal', 'legitimate', 'lethal', 'level', 'lewd', 'light', 'lighthearted', 'likable', 'like', 'likeable', 'likely', 'limited', 'limp', 'limping', 'linear', 'lined', 'liquid', 'literate', 'little', 'live', 'lively', 'livid', 'living', 'loathsome', 'lone', 'lonely', 'long', 'longing', 'long-term', 'loose', 'lopsided', 'lost', 'loud', 'loutish', 'lovable', 'lovely', 'loving', 'low', 'lowly', 'loyal', 'lucky', 'ludicrous', 'lumbering', 'luminous', 'lumpy', 'lush', 'lustrous', 'luxuriant', 'luxurious', 'lying', 'lyrical'], - 'm': - ['macabre', 'macho', 'mad', 'maddening', 'made-up', 'madly', 'magenta', 'magical', 'magnificent', 'majestic', 'major', 'makeshift', 'male', 'malicious', 'mammoth', 'maniacal', 'many', 'marked', 'married', 'marvelous', 'masculine', 'massive', 'material', 'materialistic', 'mature', 'meager', 'mealy', 'mean', 'measly', 'meaty', 'medical', 'mediocre', 'medium', 'meek', 'melancholy', 'mellow', 'melodic', 'melted', 'memorable', 'menacing', 'merciful', 'mere', 'merry', 'messy', 'metallic', 'mighty', 'mild', 'military', 'milky', 'mindless', 'miniature', 'minor', 'minty', 'minute', 'miscreant', 'miserable', 'miserly', 'misguided', 'mistaken', 'misty', 'mixed', 'moaning', 'modern', 'modest', 'moist', 'moldy', 'momentous', 'monstrous', 'monthly', 'monumental', 'moody', 'moral', 'mortified', 'motherly', 'motionless', 'mountainous', 'muddled', 'muddy', 'muffled', 'multicolored', 'mundane', 'mundane', 'murky', 'mushy', 'musty', 'mute', 'muted', 'mysterious'], - 'n': - ['naive', 'nappy', 'narrow', 'nasty', 'natural', 'naughty', 'nauseating', 'nautical', 'near', 'neat', 'nebulous', 'necessary', 'needless', 'needy', 'negative', 'neglected', 'negligible', 'neighboring', 'neighborly', 'nervous', 'nervous', 'new', 'next', 'nice', 'nice', 'nifty', 'nimble', 'nine', 'nippy', 'nocturnal', 'noiseless', 'noisy', 'nonchalant', 'nondescript', 'nonsensical', 'nonstop', 'normal', 'nostalgic', 'nosy', 'notable', 'noted', 'noteworthy', 'novel', 'noxious', 'null', 'numb', 'numberless', 'numerous', 'nutritious', 'nutty'], - 'o': - ['oafish', 'obedient', 'obeisant', 'obese', 'oblivious', 'oblong', 'obnoxious', 'obscene', 'obsequious', 'observant', 'obsolete', 'obtainable', 'obvious', 'occasional', 'oceanic', 'odd', 'oddball', 'offbeat', 'offensive', 'official', 'oily', 'old', 'old-fashioned', 'omniscient', 'one', 'onerous', 'only', 'open', 'opposite', 'optimal', 'optimistic', 'opulent', 'orange', 'orderly', 'ordinary', 'organic', 'original', 'ornate', 'ornery', 'ossified', 'other', 'our', 'outgoing', 'outlandish', 'outlying', 'outrageous', 'outstanding', 'oval', 'overconfident', 'overcooked', 'overdue', 'overjoyed', 'overlooked', 'overrated', 'overt', 'overwrought'], - 'p': - ['painful', 'painstaking', 'palatable', 'pale', 'paltry', 'panicky', 'panoramic', 'parallel', 'parched', 'parsimonious', 'partial', 'passionate', 'past', 'pastel', 'pastoral', 'pathetic', 'peaceful', 'penitent', 'peppery', 'perfect', 'perfumed', 'periodic', 'perky', 'permissible', 'perpetual', 'perplexed', 'personal', 'pertinent', 'pesky', 'pessimistic', 'petite', 'petty', 'petty', 'phobic', 'phony', 'physical', 'picayune', 'piercing', 'pink', 'piquant', 'pitiful', 'placid', 'plain', 'plaintive', 'plant', 'plastic', 'plausible', 'playful', 'pleasant', 'pleased', 'pleasing', 'plucky', 'plump', 'plush', 'pointed', 'pointless', 'poised', 'polished', 'polite', 'political', 'pompous', 'poor', 'popular', 'portly', 'posh', 'positive', 'possessive', 'possible', 'potable', 'powerful', 'powerless', 'practical', 'precious', 'premium', 'present', 'present', 'prestigious', 'pretty', 'previous', 'pricey', 'prickly', 'primary', 'prime', 'pristine', 'private', 'prize', 'probable', 'productive', 'profitable', 'profuse', 'proper', 'protective', 'proud', 'prudent', 'psychedelic', 'psychotic', 'public', 'puffy', 'pumped', 'punctual', 'pungent', 'puny', 'pure', 'purple', 'purring', 'pushy', 'pushy', 'putrid', 'puzzled', 'puzzling'], - 'q': - ['quack', 'quaint', 'quaint', 'qualified', 'quarrelsome', 'quarterly', 'queasy', 'querulous', 'questionable', 'quick', 'quickest', 'quick-witted', 'quiet', 'quintessential', 'quirky', 'quixotic', 'quixotic', 'quizzical'], - 'r': - ['rabid', 'racial', 'radiant', 'ragged', 'rainy', 'rambunctious', 'rampant', 'rapid', 'rare', 'rash', 'raspy', 'ratty', 'raw', 'ready', 'real', 'realistic', 'reasonable', 'rebel', 'recent', 'receptive', 'reckless', 'recondite', 'rectangular', 'red', 'redundant', 'reflecting', 'reflective', 'regal', 'regular', 'reliable', 'relieved', 'remarkable', 'reminiscent', 'remorseful', 'remote', 'repentant', 'repulsive', 'required', 'resolute', 'resonant', 'respectful', 'responsible', 'responsive', 'revolving', 'rewarding', 'rhetorical', 'rich', 'right', 'righteous', 'rightful', 'rigid', 'ringed', 'ripe', 'ritzy', 'roasted', 'robust', 'romantic', 'roomy', 'rosy', 'rotating', 'rotten', 'rotund', 'rough', 'round', 'rowdy', 'royal', 'rubbery', 'ruddy', 'rude', 'rundown', 'runny', 'rural', 'rustic rusty', 'ruthless'], - 's': - ['sable', 'sad', 'safe', 'salty', 'same', 'sandy', 'sane', 'sarcastic', 'sardonic', 'sassy', 'satisfied', 'satisfying', 'savory', 'scaly', 'scandalous', 'scant', 'scarce', 'scared', 'scary', 'scattered', 'scented', 'scholarly', 'scientific', 'scintillating', 'scornful', 'scratchy', 'scrawny', 'screeching', 'second', 'secondary', 'second-hand', 'secret', 'secretive', 'sedate', 'seemly', 'selective', 'self-assured', 'selfish', 'self-reliant', 'sentimental', 'separate', 'serene', 'serious', 'serpentine', 'several', 'severe', 'shabby', 'shadowy', 'shady', 'shaggy', 'shaky', 'shallow', 'shameful', 'shameless', 'sharp', 'shimmering', 'shiny', 'shivering', 'shocked', 'shocking', 'shoddy', 'short', 'short-term', 'showy', 'shrill', 'shut', 'shy', 'sick', 'silent', 'silky', 'silly', 'silver', 'similar', 'simple', 'simplistic', 'sincere', 'sinful', 'single', 'six', 'sizzling', 'skeletal', 'skillful', 'skinny', 'sleepy', 'slight', 'slim', 'slimy', 'slippery', 'sloppy', 'slow', 'slushy', 'small', 'smarmy', 'smart', 'smelly', 'smiling', 'smoggy', 'smooth', 'smug', 'snappy', 'snarling', 'sneaky', 'sniveling', 'snobbish', 'snoopy', 'snotty', 'sociable', 'soft', 'soggy', 'solid', 'somber', 'some', 'sophisticated', 'sordid', 'sore', 'sorrowful', 'soulful', 'soupy', 'sour', 'sour', 'Spanish', 'sparkling', 'sparse', 'special', 'specific', 'spectacular', 'speedy', 'spherical', 'spicy', 'spiffy', 'spiky', 'spirited', 'spiritual', 'spiteful', 'splendid', 'spooky', 'spotless', 'spotted', 'spotty', 'spry', 'spurious', 'squalid', 'square', 'squeaky', 'squealing', 'squeamish', 'squiggly', 'stable', 'staid', 'stained', 'staking', 'stale', 'standard', 'standing', 'starchy', 'stark', 'starry', 'statuesque', 'steadfast', 'steady', 'steel', 'steep', 'stereotyped', 'sticky', 'stiff', 'stimulating', 'stingy', 'stormy', 'stout', 'straight', 'strange', 'strict', 'strident', 'striking', 'striped', 'strong', 'studious', 'stunning', 'stunning', 'stupendous', 'stupid', 'sturdy', 'stylish', 'subdued', 'submissive', 'subsequent', 'substantial', 'subtle', 'suburban', 'successful', 'succinct', 'succulent', 'sudden', 'sugary', 'sulky', 'sunny', 'super', 'superb', 'superficial', 'superior', 'supportive', 'supreme', 'sure-footed', 'surprised', 'suspicious', 'svelte', 'swanky', 'sweaty', 'sweet', 'sweltering', 'swift', 'sympathetic', 'symptomatic', 'synonymous'], - 't': - ['taboo', 'tacit', 'tacky', 'talented', 'talkative', 'tall', 'tame', 'tan', 'tangible', 'tangy', 'tart', 'tasteful', 'tasteless', 'tasty', 'tattered', 'taut', 'tawdry', 'tearful', 'tedious', 'teeming', 'teeny', 'teeny-tiny', 'telling', 'temporary', 'tempting', 'ten', 'tender', 'tense', 'tenuous', 'tepid', 'terrible', 'terrific', 'tested', 'testy', 'thankful', 'that', 'therapeutic', 'these', 'thick', 'thin', 'thinkable', 'third', 'thirsty', 'this', 'thorny', 'thorough', 'those', 'thoughtful', 'thoughtless', 'threadbare', 'threatening', 'three', 'thrifty', 'thundering', 'thunderous', 'tidy', 'tight', 'tightfisted', 'timely', 'tinted', 'tiny', 'tired', 'tiresome', 'toothsome', 'torn', 'torpid', 'total', 'tough', 'towering', 'tragic', 'trained', 'tranquil', 'trashy', 'traumatic', 'treasured', 'tremendous', 'triangular', 'tricky', 'trifling', 'trim', 'trite', 'trivial', 'troubled', 'truculent', 'true', 'trusting', 'trustworthy', 'trusty', 'truthful', 'tubby', 'turbulent', 'twin', 'two', 'typical'], - 'u': - ['ubiquitous', 'ugliest', 'ugly', 'ultimate', 'ultra', 'unable', 'unaccountable', 'unarmed', 'unaware', 'unbecoming', 'unbiased', 'uncomfortable', 'uncommon', 'unconscious', 'uncovered', 'understated', 'understood', 'undesirable', 'unequal', 'unequaled', 'uneven', 'unfinished', 'unfit', 'unfolded', 'unfortunate', 'unhappy', 'unhealthy', 'uniform', 'unimportant', 'uninterested', 'unique', 'united', 'unkempt', 'unknown', 'unlawful', 'unlined', 'unlucky', 'unnatural', 'unpleasant', 'unrealistic', 'unripe', 'unruly', 'unselfish', 'unsightly', 'unsteady', 'unsuitable', 'unsung', 'untidy', 'untimely', 'untried', 'untrue', 'unused', 'unusual', 'unwelcome', 'unwieldy', 'unwitting', 'unwritten', 'upbeat', 'uppity', 'upright', 'upset', 'uptight', 'urban', 'usable', 'used', 'used', 'useful', 'useless', 'utilized', 'utopian', 'utter', 'uttermost'], - 'v': - ['vacant', 'vacuous', 'vagabond', 'vague', 'vain', 'valid', 'valuable', 'vapid', 'variable', 'various', 'vast', 'velvety', 'venerated', 'vengeful', 'venomous', 'verdant', 'verifiable', 'versed', 'vexed', 'vibrant', 'vicious', 'victorious', 'vigilant', 'vigorous', 'villainous', 'violent', 'violet', 'virtual', 'virtuous', 'visible', 'vital', 'vivacious', 'vivid', 'voiceless', 'volatile', 'voluminous', 'voracious', 'vulgar'], - 'w': - ['wacky', 'waggish', 'waiting', 'wakeful', 'wan', 'wandering', 'wanting', 'warlike', 'warm', 'warmhearted', 'warped', 'wary', 'wasteful', 'watchful', 'waterlogged', 'watery', 'wavy', 'weak', 'wealthy', 'weary', 'webbed', 'wee', 'weekly', 'weepy', 'weighty', 'weird', 'welcome', 'well-documented', 'well-groomed', 'well-informed', 'well-lit', 'well-made', 'well-off', 'well-to-do', 'well-worn', 'wet', 'which', 'whimsical', 'whirlwind', 'whispered', 'whispering', 'white', 'whole', 'wholesale', 'whopping', 'wicked', 'wide', 'wide-eyed', 'wiggly', 'wild', 'willing', 'wilted', 'winding', 'windy', 'winged', 'wiry', 'wise', 'wistful', 'witty', 'wobbly', 'woebegone', 'woeful', 'womanly', 'wonderful', 'wooden', 'woozy', 'wordy', 'workable', 'worldly', 'worn', 'worried', 'worrisome', 'worse', 'worst', 'worthless', 'worthwhile', 'worthy', 'wrathful', 'wretched', 'writhing', 'wrong', 'wry'], - 'x': - ['xenophobic'], - 'y': - ['yawning', 'yearly', 'yellow', 'yellowish', 'yielding', 'young', 'youthful', 'yummy'], - 'z': - ['zany', 'zealous', 'zesty', 'zigzag', 'zippy', 'zonked'] - }.freeze - SCIENTISTS = { - 'a': - ['Louis Agassiz', 'Maria Gaetana Agnesi', 'Al-Battani', 'Abu Nasr Al-Farabi', 'Jim Al-Khalili', 'Muhammad ibn Musa al-Khwarizmi', 'Mihailo Petrovic Alas', 'Angel Alcala', 'Salim Ali', 'Luis Alvarez', 'Andre Marie Ampère', 'Anaximander', 'Mary Anning', 'Virginia Apgar', 'Archimedes', 'Agnes Arber', 'Aristarchus', 'Aristotle', 'Svante Arrhenius', 'Oswald Avery', 'Amedeo Avogadro', 'Avicenna'], - 'b': - ['Charles Babbage', 'Francis Bacon', 'Alexander Bain', 'John Logie Baird', 'Joseph Banks', 'Ramon Barba', 'John Bardeen', 'Ibn Battuta', 'William Bayliss', 'George Beadle', 'Arnold Orville Beckman', 'Henri Becquerel', 'Emil Adolf Behring', 'Alexander Graham Bell', 'Emile Berliner', 'Claude Bernard', 'Timothy John Berners-Lee', 'Daniel Bernoulli', 'Jacob Berzelius', 'Henry Bessemer', 'Hans Bethe', 'Homi Jehangir Bhabha', 'Alfred Binet', 'Clarence Birdseye', 'Kristian Birkeland', 'Elizabeth Blackwell', 'Alfred Blalock', 'Katharine Burr Blodgett', 'Franz Boas', 'David Bohm', 'Aage Bohr', 'Niels Bohr', 'Ludwig Boltzmann', 'Max Born', 'Carl Bosch', 'Robert Bosch', 'Jagadish Chandra Bose', 'Satyendra Nath Bose', 'Walther Wilhelm Georg Bothe', 'Robert Boyle', 'Lawrence Bragg', 'Tycho Brahe', 'Brahmagupta', 'Georg Brandt', 'Wernher Von Braun', 'Louis de Broglie', 'Alexander Brongniart', 'Robert Brown', 'Michael E. Brown', 'Lester R. Brown', 'Eduard Buchner', 'William Buckland', 'Georges-Louis Leclerc, Comte de Buffon', 'Robert Bunsen', 'Luther Burbank', 'Jocelyn Bell Burnell', 'Thomas Burnet'], - 'c': - ['Benjamin Cabrera', 'Santiago Ramon y Cajal', 'Rachel Carson', 'George Washington Carver', 'Henry Cavendish', 'Anders Celsius', 'James Chadwick', 'Subrahmanyan Chandrasekhar', 'Erwin Chargaff', 'Noam Chomsky', 'Steven Chu', 'Leland Clark', 'Arthur Compton', 'Nicolaus Copernicus', 'Gerty Theresa Cori', 'Charles-Augustin de Coulomb', 'Jacques Cousteau', 'Brian Cox', 'Francis Crick', 'Nicholas Culpeper', 'Marie Curie', 'Pierre Curie', 'Georges Cuvier', 'Adalbert Czerny'], - 'd': - ['Gottlieb Daimler', 'John Dalton', 'James Dwight Dana', 'Charles Darwin', 'Humphry Davy', 'Peter Debye', 'Max Delbruck', 'Jean Andre Deluc', 'René Descartes', 'Rudolf Christian Karl Diesel', 'Paul Dirac', 'Prokop Divis', 'Theodosius Dobzhansky', 'Frank Drake', 'K. Eric Drexler'], - 'e': - ['Arthur Eddington', 'Thomas Edison', 'Paul Ehrlich', 'Albert Einstein', 'Gertrude Elion', 'Empedocles', 'Eratosthenes', 'Euclid', 'Leonhard Euler'], - 'f': - ['Michael Faraday', 'Pierre de Fermat', 'Enrico Fermi', 'Richard Feynman', 'Fibonacci – Leonardo of Pisa', 'Emil Fischer', 'Ronald Fisher', 'Alexander Fleming', 'Henry Ford', 'Lee De Forest', 'Dian Fossey', 'Leon Foucault', 'Benjamin Franklin', 'Rosalind Franklin', 'Sigmund Freud'], - 'g': - ['Galen', 'Galileo Galilei', 'Francis Galton', 'Luigi Galvani', 'George Gamow', 'Carl Friedrich Gauss', 'Murray Gell-Mann', 'Sophie Germain', 'Willard Gibbs', 'William Gilbert', 'Sheldon Lee Glashow', 'Robert Goddard', 'Maria Goeppert-Mayer', 'Jane Goodall', 'Stephen Jay Gould'], - 'h': - ['Fritz Haber', 'Ernst Haeckel', 'Otto Hahn', 'Albrecht von Haller', 'Edmund Halley', 'Thomas Harriot', 'William Harvey', 'Stephen Hawking', 'Otto Haxel', 'Werner Heisenberg', 'Hermann von Helmholtz', 'Jan Baptist von Helmont', 'Joseph Henry', 'William Herschel', 'Gustav Ludwig Hertz', 'Heinrich Hertz', 'Karl F. Herzfeld', 'Antony Hewish', 'David Hilbert', 'Maurice Hilleman', 'Hipparchus', 'Hippocrates', 'Shintaro Hirase', 'Dorothy Hodgkin', 'Robert Hooke', 'Frederick Gowland Hopkins', 'William Hopkins', 'Grace Murray Hopper', 'Frank Hornby', 'Jack Horner', 'Bernardo Houssay', 'Fred Hoyle', 'Edwin Hubble', 'Alexander von Humboldt', 'Zora Neale Hurston', 'James Hutton', 'Christiaan Huygens'], - 'i': - ['Ernesto Illy', 'Ernst Ising', 'Keisuke Ito'], - 'j': - ['Mae Carol Jemison', 'Edward Jenner', 'J. Hans D. Jensen', 'Irene Joliot-Curie', 'James Prescott Joule', 'Percy Lavon Julian'], - 'k': - ['Michio Kaku', 'Heike Kamerlingh Onnes', 'Friedrich August Kekulé', 'Frances Kelsey', 'Pearl Kendrick', 'Johannes Kepler', 'Abdul Qadeer Khan', 'Omar Khayyam', 'Alfred Kinsey', 'Gustav Kirchoff', 'Robert Koch', 'Emil Kraepelin', 'Thomas Kuhn', 'Stephanie Kwolek'], - 'l': - ['Jean-Baptiste Lamarck', 'Hedy Lamarr', 'Edwin Herbert Land', 'Karl Landsteiner', 'Pierre-Simon Laplace', 'Max von Laue', 'Antoine Lavoisier', 'Ernest Lawrence', 'Henrietta Leavitt', 'Antonie van Leeuwenhoek', 'Inge Lehmann', 'Gottfried Leibniz', 'Georges Lemaître', 'Leonardo da Vinci', 'Niccolo Leoniceno', 'Aldo Leopold', 'Rita Levi-Montalcini', 'Claude Levi-Strauss', 'Willard Frank Libby', 'Justus von Liebig', 'Carolus Linnaeus', 'Joseph Lister', 'John Locke', 'Hendrik Antoon Lorentz', 'Konrad Lorenz', 'Ada Lovelace', 'Lucretius', 'Charles Lyell', 'Trofim Lysenko'], - 'm': - ['Ernst Mach', 'Marcello Malpighi', 'Jane Marcet', 'Guglielmo Marconi', 'Lynn Margulis', 'James Clerk Maxwell', 'Ernst Mayr', 'Barbara McClintock', 'Lise Meitner', 'Gregor Mendel', 'Dmitri Mendeleev', 'Franz Mesmer', 'Antonio Meucci', 'Albert Abraham Michelson', 'Thomas Midgeley Jr.', 'Maria Mitchell', 'Mario Molina', 'Thomas Hunt Morgan', 'Henry Moseley'], - 'n': - ['Ukichiro Nakaya', 'John Napier', 'John Needham', 'John von Neumann', 'Thomas Newcomen', 'Isaac Newton', 'Florence Nightingale', 'Tim Noakes', 'Alfred Nobel', 'Emmy Noether', 'Christiane Nusslein-Volhard', 'Bill Nye'], - 'o': - ['Hans Christian Oersted', 'Georg Ohm', 'J. Robert Oppenheimer', 'Wilhelm Ostwald'], - 'p': - ['Blaise Pascal', 'Louis Pasteur', 'Wolfgang Ernst Pauli', 'Linus Pauling', 'Randy Pausch', 'Ivan Pavlov', 'Marguerite Perey', 'Jean Piaget', 'Philippe Pinel', 'Max Planck', 'Pliny the Elder', 'Karl Popper', 'Beatrix Potter', 'Joseph Priestley', 'Claudius Ptolemy', 'Pythagoras'], - 'q': - ['Harriet Quimby', 'Thabit ibn Qurra'], - 'r': - ['C. V. Raman', 'Srinivasa Ramanujan', 'William Ramsay', 'John Ray', 'Prafulla Chandra Ray', 'Francesco Redi', 'Sally Ride', 'Bernhard Riemann', 'Wilhelm Röntgen', 'Hermann Rorschach', 'Ronald Ross', 'Ibn Rushd', 'Ernest Rutherford'], - 's': - ['Carl Sagan', 'Mohammad Abdus Salam', 'Jonas Salk', 'Frederick Sanger', 'Alberto Santos-Dumont', 'Walter Schottky', 'Erwin Schrödinger', 'Theodor Schwann', 'Glenn Seaborg', 'Hans Selye', 'Charles Sherrington', 'Gene Shoemaker', 'Ernst Werner von Siemens', 'George Gaylord Simpson', 'B. F. Skinner', 'William Smith', 'Frederick Soddy', 'Arnold Sommerfeld', 'Nettie Stevens', 'William John Swainson', 'Leo Szilard'], - 't': - ['Niccolo Tartaglia', 'Edward Teller', 'Nikola Tesla', 'Thales of Miletus', 'Benjamin Thompson', 'J. J. Thomson', 'William Thomson', 'Henry David Thoreau', 'Kip S. Thorne', 'Clyde Tombaugh', 'Evangelista Torricelli', 'Charles Townes', 'Alan Turing', 'Neil deGrasse Tyson'], - 'u': - ['Harold Urey'], - 'v': - ['Craig Venter', 'Vladimir Vernadsky', 'Andreas Vesalius', 'Rudolf Virchow', 'Artturi Virtanen', 'Alessandro Volta'], - 'w': - ['George Wald', 'Alfred Russel Wallace', 'James Watson', 'James Watt', 'Alfred Wegener', 'John Archibald Wheeler', 'Maurice Wilkins', 'Thomas Willis', 'E. O. Wilson', 'Sven Wingqvist', 'Sergei Winogradsky', 'Friedrich Wöhler', 'Wilbur and Orville Wright', 'Wilhelm Wundt'], - 'x': - [], - 'y': - ['Chen-Ning Yang'], - 'z': - ['Ahmed Zewail'] - }.freeze - - desc 'Generate a new release name' - task generate_release_name: :environment do - def rand_el(arr) - arr[rand(arr.count)] - end - - puts '------------------------------------' - puts '' - puts 'sciNote release name generator v0.1 ALPHA' - puts '' - puts '------------------------------------' - - puts '' - puts 'Choose what you would like to do:' - puts '1) Provide a scientist by yourself' - puts '2) Randomly choose a scientist from a pre-defined list' - res = $stdin.gets.strip - unless res.in?(['', '1', '2']) - puts 'Invalid parameter, exiting' - next - end - - # First, pick scientist name - if res.in?(['', '1']) - puts 'Enter full scientist first name (all but surname) ' \ - 'in capitalized case' - first_name = $stdin.gets.strip - puts 'Enter full scientist surname ' \ - 'in capitalized case' - last_name = $stdin.gets.strip - key = last_name[0].downcase.to_sym - full_name = "#{first_name} #{last_name}" - else - key = rand_el(SCIENTISTS.keys) - full_name = rand_el(SCIENTISTS[key]) - last_name = full_name.split(' ')[-1] - puts "Randomly chosen scientist: #{full_name}" - puts '' - end - - # Now, pick adjective - adjective = rand_el(ADJECTIVES[key]) - - puts '------------------------------------' - puts 'Tadaaaa!' - puts 'The new release will be named......' - puts '(waaaaait for iiiiit)' - puts '' - puts '##############################################' - puts " #{adjective.capitalize} #{last_name}" - puts " (full name: #{full_name})" - puts '##############################################' - - loop do - puts '' - puts 'What would you like to do?' - puts '(E) Exit' - puts '(a) generate new adjective' - puts '(s) generate new random scientist' - res = $stdin.gets.strip - unless res.in?(['', 'e', 'E', 'a', 'A', 's', 'S']) - puts 'Invalid parameter!' - next - end - - break if res.in?(['', 'e', 'E']) - - if res.in?(%w(s S)) - key = rand_el(SCIENTISTS.keys) - full_name = rand_el(SCIENTISTS[key]) - last_name = full_name.split(' ')[-1] - end - - adjective = rand_el(ADJECTIVES[key]) - - puts '' - puts '##############################################' - puts " #{adjective.capitalize} #{last_name} " - puts " (full name: #{full_name})" - puts '##############################################' - end - end -end diff --git a/lib/tasks/versions/adjectives.json b/lib/tasks/versions/adjectives.json new file mode 100644 index 000000000..9d024b18f --- /dev/null +++ b/lib/tasks/versions/adjectives.json @@ -0,0 +1,54 @@ +{ + "a": + ["aback", "abaft", "abandoned", "abashed", "aberrant", "abhorrent", "abiding", "abject", "ablaze", "able", "abnormal", "aboard", "aboriginal", "abortive", "abounding", "abrasive", "abrupt", "absent", "absolute", "absorbed", "absorbing", "abstracted", "absurd", "abundant", "abusive", "academic", "acceptable", "accessible", "accidental", "acclaimed", "accomplished", "accurate", "aching", "acid", "acidic", "acoustic", "acrid", "acrobatic", "active", "actual", "actually", "ad hoc", "adamant", "adaptable", "addicted", "adept", "adhesive", "adjoining", "admirable", "admired", "adolescent", "adorable", "adored", "advanced", "adventurous", "affectionate", "afraid", "aged", "aggravating", "aggressive", "agile", "agitated", "agonizing", "agreeable", "ahead", "ajar", "alarmed", "alarming", "alcoholic", "alert", "alienated", "alike", "alive", "all", "alleged", "alluring", "aloof", "altruistic", "amazing", "ambiguous", "ambitious", "amiable", "ample", "amuck", "amused", "amusing", "anchored", "ancient", "ancient", "angelic", "angry", "angry", "anguished", "animated", "annoyed", "annoying", "annual", "another", "antique", "antsy", "anxious", "any", "apathetic", "appetizing", "apprehensive", "appropriate", "apt", "aquatic", "arctic", "arid", "aromatic", "arrogant", "artistic", "ashamed", "aspiring", "assorted", "assured", "astonishing", "athletic", "attached", "attentive", "attractive", "auspicious", "austere", "authentic", "authorized", "automatic", "available", "avaricious", "average", "awake", "aware", "awesome", "awful", "awkward", "axiomatic"], + "b": + ["babyish", "back", "bad", "baggy", "barbarous", "bare", "barren", "bashful", "basic", "batty", "bawdy", "beautiful", "beefy", "befitting", "belated", "belligerent", "beloved", "beneficial", "bent", "berserk", "best", "better", "bewildered", "bewitched", "big", "big-hearted", "billowy", "biodegradable", "bite-sized", "biting", "bitter", "bizarre", "black", "black-and-white", "bland", "blank", "blaring", "bleak", "blind", "blissful", "blond", "bloody", "blue", "blue-eyed", "blushing", "bogus", "boiling", "bold", "bony", "boorish", "bored", "boring", "bossy", "both", "bouncy", "boundless", "bountiful", "bowed", "brainy", "brash", "brave", "brawny", "breakable", "breezy", "brief", "bright", "brilliant", "brisk", "broad", "broken", "bronze", "brown", "bruised", "bubbly", "bulky", "bumpy", "buoyant", "burdensome", "burly", "bustling", "busy", "buttery", "buzzing"], + "c": + ["cagey", "calculating", "callous", "calm", "candid", "canine", "capable", "capital", "capricious", "carefree", "careful", "careless", "caring", "cautious", "cavernous", "ceaseless", "celebrated", "certain", "changeable", "charming", "cheap", "cheeky", "cheerful", "cheery", "chemical", "chief", "childlike", "chilly", "chivalrous", "chubby", "chunky", "circular", "clammy", "classic", "classy", "clean", "clear", "clear-cut", "clever", "cloistered", "close", "closed", "cloudy", "clueless", "clumsy", "cluttered", "coarse", "coherent", "cold", "colorful", "colorless", "colossal", "colossal", "combative", "comfortable", "common", "compassionate", "competent", "complete", "complex", "complicated", "composed", "concerned", "concrete", "condemned", "condescending", "confused", "conscious", "considerate", "constant", "contemplative", "content", "conventional", "convincing", "convoluted", "cooing", "cooked", "cool", "cooperative", "coordinated", "corny", "corrupt", "costly", "courageous", "courteous", "cowardly", "crabby", "crafty", "craven", "crazy", "creamy", "creative", "creepy", "criminal", "crisp", "critical", "crooked", "crowded", "cruel", "crushing", "cuddly", "cultivated", "cultured", "cumbersome", "curious", "curly", "curved", "curvy", "cut", "cute", "cylindrical", "cynical"], + "d": + ["daffy", "daily", "damaged", "damaging", "damp", "dangerous", "dapper", "dapper", "daring", "dark", "darling", "dashing", "dazzling", "dead", "deadly", "deadpan", "deafening", "dear", "dearest", "debonair", "decayed", "deceitful", "decent", "decimal", "decisive", "decorous", "deep", "deeply", "defeated", "defective", "defenseless", "defensive", "defiant", "deficient", "definite", "delayed", "delectable", "delicate", "delicious", "delightful", "delirious", "demanding", "demonic", "dense", "dental", "dependable", "dependent", "depraved", "depressed", "deranged", "descriptive", "deserted", "despicable", "detailed", "determined", "devilish", "devoted", "didactic", "different", "difficult", "digital", "dilapidated", "diligent", "dim", "diminutive", "dimpled", "dimwitted", "direct", "direful", "dirty", "disagreeable", "disastrous", "discreet", "discrete", "disfigured", "disguised", "disgusted", "disgusting", "dishonest", "disillusioned", "disloyal", "dismal", "dispensable", "distant", "distinct", "distorted", "distraught", "distressed", "disturbed", "divergent", "dizzy", "domineering", "dopey", "doting", "double", "doubtful", "downright", "drab", "draconian", "drafty", "drained", "dramatic", "dreary", "droopy", "drunk", "dry", "dual", "dull", "dull", "dusty", "dutiful", "dynamic", "dysfunctional"], + "e": + ["each", "eager", "early", "earnest", "earsplitting", "earthy", "easy", "easy-going", "eatable", "economic", "ecstatic", "edible", "educated", "efficacious", "efficient", "eight", "elaborate", "elastic", "elated", "elderly", "electric", "elegant", "elementary", "elfin", "elite", "elliptical", "emaciated", "embarrassed", "embellished", "eminent", "emotional", "empty", "enchanted", "enchanting", "encouraging", "endurable", "energetic", "enlightened", "enormous", "enraged", "entertaining", "enthusiastic", "entire", "envious", "envious", "equable", "equal", "equatorial", "erect", "erratic", "essential", "esteemed", "ethereal", "ethical", "euphoric", "evanescent", "evasive", "even", "evergreen", "everlasting", "every", "evil", "exalted", "exasperated", "excellent", "excitable", "excited", "exciting", "exclusive", "exemplary", "exhausted", "exhilarated", "exotic", "expensive", "experienced", "expert", "extensive", "extra-large", "extraneous", "extra-small", "extroverted", "exuberant", "exultant"], + "f": + ["fabulous", "faded", "failing", "faint", "fair", "faithful", "fake", "fallacious", "false", "familiar", "famous", "fanatical", "fancy", "fantastic", "far", "faraway", "far-flung", "far-off", "fascinated", "fast", "fat", "fatal", "fatherly", "faulty", "favorable", "favorite", "fearful", "fearless", "feeble", "feigned", "feisty", "feline", "female", "feminine", "fertile", "festive", "few", "fickle", "fierce", "filthy", "fine", "finicky", "finished", "firm", "first", "firsthand", "fitting", "five", "fixed", "flagrant", "flaky", "flamboyant", "flashy", "flat", "flawed", "flawless", "flickering", "flimsy", "flippant", "floppy", "flowery", "flufy", "fluid", "flustered", "fluttering", "foamy", "focused", "fond", "foolhardy", "foolish", "forceful", "foregoing", "forgetful", "forked", "formal", "forsaken", "forthright", "fortunate", "four", "fragile", "fragrant", "frail", "frank", "frantic", "frayed", "free", "freezing", "French", "frequent", "fresh", "fretful", "friendly", "frightened", "frightening", "frigid", "frilly", "frivolous", "frizzy", "front", "frosty", "frothy", "frozen", "frugal", "fruitful", "frustrating", "full", "fumbling", "fumbling", "functional", "funny", "furry", "furtive", "fussy", "future", "futuristic", "fuzzy"], + "g": + ["gabby", "gainful", "gamy", "gaping", "gargantuan", "garrulous", "gaseous", "gaudy", "general", "general", "generous", "gentle", "genuine", "ghastly", "giant", "giddy", "gifted", "gigantic", "giving", "glamorous", "glaring", "glass", "gleaming", "gleeful", "glib", "glistening", "glittering", "gloomy", "glorious", "glossy", "glum", "godly", "golden", "good", "good-natured", "goofy", "gorgeous", "graceful", "gracious", "grand", "grandiose", "grandiose", "granular", "grateful", "gratis", "grave", "gray", "greasy", "great", "greedy", "green", "gregarious", "grey", "grieving", "grim", "grimy", "gripping", "grizzled", "groovy", "gross", "grotesque", "grouchy", "grounded", "growing", "growling", "grown", "grubby", "gruesome", "grumpy", "guarded", "guiltless", "guilty", "gullible", "gummy", "gusty", "guttural"], + "h": + ["habitual", "hairy", "half", "half", "hallowed", "halting", "handmade", "handsome", "handsomely", "handy", "hanging", "hapless", "happy", "happy-go-lucky", "hard", "hard-to-find", "harebrained", "harmful", "harmless", "harmonious", "harsh", "hasty", "hateful", "haunting", "heady", "healthy", "heartbreaking", "heartfelt", "hearty", "heavenly", "heavy", "hefty", "hellish", "helpful", "helpless", "hesitant", "hidden", "hideous", "high", "highfalutin", "high-level", "high-pitched", "hilarious", "hissing", "historical", "hoarse", "holistic", "hollow", "homeless", "homely", "honest", "honorable", "honored", "hopeful", "horrible", "horrific", "hospitable", "hot", "huge", "hulking", "humble", "humdrum", "humiliating", "humming", "humongous", "humorous", "hungry", "hurried", "hurt", "hurtful", "hushed", "husky", "hypnotic", "hysterical"], + "i": + ["icky", "icy", "ideal", "ideal", "idealistic", "identical", "idiotic", "idle", "idolized", "ignorant", "ill", "illegal", "ill-fated", "ill-informed", "illiterate", "illustrious", "imaginary", "imaginative", "immaculate", "immaterial", "immediate", "immense", "imminent", "impartial", "impassioned", "impeccable", "imperfect", "imperturbable", "impish", "impolite", "important", "imported", "impossible", "impractical", "impressionable", "impressive", "improbable", "impure", "inborn", "incandescent", "incomparable", "incompatible", "incompetent", "incomplete", "inconclusive", "inconsequential", "incredible", "indelible", "indolent", "industrious", "inexpensive", "inexperienced", "infamous", "infantile", "infatuated", "inferior", "infinite", "informal", "innate", "innocent", "inquisitive", "insecure", "insidious", "insignificant", "insistent", "instinctive", "instructive", "insubstantial", "intelligent", "intent", "intentional", "interesting", "internal", "international", "intrepid", "intrigued", "invincible", "irate", "ironclad", "irresponsible", "irritable", "irritating", "itchy"], + "j": + ["jaded", "jagged", "jam-packed", "jaunty", "jazzy", "jealous", "jittery", "jobless", "joint", "jolly", "jovial", "joyful", "joyous", "jubilant", "judicious", "juicy", "jumbled", "jumbo", "jumpy", "jumpy", "junior", "juvenile"], + "k": + ["kaleidoscopic", "kaput", "keen", "key", "kind", "kindhearted", "kindly", "klutzy", "knobby", "knotty", "knowing", "knowledgeable", "known", "kooky", "kosher"], + "l": + ["labored", "lackadaisical", "lacking", "lame", "lame", "lamentable", "languid", "lanky", "large", "last", "lasting", "late", "laughable", "lavish", "lawful", "lazy", "leading", "leafy", "lean", "learned", "left", "legal", "legitimate", "lethal", "level", "lewd", "light", "lighthearted", "likable", "like", "likeable", "likely", "limited", "limp", "limping", "linear", "lined", "liquid", "literate", "little", "live", "lively", "livid", "living", "loathsome", "lone", "lonely", "long", "longing", "long-term", "loose", "lopsided", "lost", "loud", "loutish", "lovable", "lovely", "loving", "low", "lowly", "loyal", "lucky", "ludicrous", "lumbering", "luminous", "lumpy", "lush", "lustrous", "luxuriant", "luxurious", "lying", "lyrical"], + "m": + ["macabre", "macho", "mad", "maddening", "made-up", "madly", "magenta", "magical", "magnificent", "majestic", "major", "makeshift", "male", "malicious", "mammoth", "maniacal", "many", "marked", "married", "marvelous", "masculine", "massive", "material", "materialistic", "mature", "meager", "mealy", "mean", "measly", "meaty", "medical", "mediocre", "medium", "meek", "melancholy", "mellow", "melodic", "melted", "memorable", "menacing", "merciful", "mere", "merry", "messy", "metallic", "mighty", "mild", "military", "milky", "mindless", "miniature", "minor", "minty", "minute", "miscreant", "miserable", "miserly", "misguided", "mistaken", "misty", "mixed", "moaning", "modern", "modest", "moist", "moldy", "momentous", "monstrous", "monthly", "monumental", "moody", "moral", "mortified", "motherly", "motionless", "mountainous", "muddled", "muddy", "muffled", "multicolored", "mundane", "mundane", "murky", "mushy", "musty", "mute", "muted", "mysterious"], + "n": + ["naive", "nappy", "narrow", "nasty", "natural", "naughty", "nauseating", "nautical", "near", "neat", "nebulous", "necessary", "needless", "needy", "negative", "neglected", "negligible", "neighboring", "neighborly", "nervous", "nervous", "new", "next", "nice", "nice", "nifty", "nimble", "nine", "nippy", "nocturnal", "noiseless", "noisy", "nonchalant", "nondescript", "nonsensical", "nonstop", "normal", "nostalgic", "nosy", "notable", "noted", "noteworthy", "novel", "noxious", "null", "numb", "numberless", "numerous", "nutritious", "nutty"], + "o": + ["oafish", "obedient", "obeisant", "obese", "oblivious", "oblong", "obnoxious", "obscene", "obsequious", "observant", "obsolete", "obtainable", "obvious", "occasional", "oceanic", "odd", "oddball", "offbeat", "offensive", "official", "oily", "old", "old-fashioned", "omniscient", "one", "onerous", "only", "open", "opposite", "optimal", "optimistic", "opulent", "orange", "orderly", "ordinary", "organic", "original", "ornate", "ornery", "ossified", "other", "our", "outgoing", "outlandish", "outlying", "outrageous", "outstanding", "oval", "overconfident", "overcooked", "overdue", "overjoyed", "overlooked", "overrated", "overt", "overwrought"], + "p": + ["painful", "painstaking", "palatable", "pale", "paltry", "panicky", "panoramic", "parallel", "parched", "parsimonious", "partial", "passionate", "past", "pastel", "pastoral", "pathetic", "peaceful", "penitent", "peppery", "perfect", "perfumed", "periodic", "perky", "permissible", "perpetual", "perplexed", "personal", "pertinent", "pesky", "pessimistic", "petite", "petty", "petty", "phobic", "phony", "physical", "picayune", "piercing", "pink", "piquant", "pitiful", "placid", "plain", "plaintive", "plant", "plastic", "plausible", "playful", "pleasant", "pleased", "pleasing", "plucky", "plump", "plush", "pointed", "pointless", "poised", "polished", "polite", "political", "pompous", "poor", "popular", "portly", "posh", "positive", "possessive", "possible", "potable", "powerful", "powerless", "practical", "precious", "premium", "present", "present", "prestigious", "pretty", "previous", "pricey", "prickly", "primary", "prime", "pristine", "private", "prize", "probable", "productive", "profitable", "profuse", "proper", "protective", "proud", "prudent", "psychedelic", "psychotic", "public", "puffy", "pumped", "punctual", "pungent", "puny", "pure", "purple", "purring", "pushy", "pushy", "putrid", "puzzled", "puzzling"], + "q": + ["quack", "quaint", "quaint", "qualified", "quarrelsome", "quarterly", "queasy", "querulous", "questionable", "quick", "quickest", "quick-witted", "quiet", "quintessential", "quirky", "quixotic", "quixotic", "quizzical"], + "r": + ["rabid", "racial", "radiant", "ragged", "rainy", "rambunctious", "rampant", "rapid", "rare", "rash", "raspy", "ratty", "raw", "ready", "real", "realistic", "reasonable", "rebel", "recent", "receptive", "reckless", "recondite", "rectangular", "red", "redundant", "reflecting", "reflective", "regal", "regular", "reliable", "relieved", "remarkable", "reminiscent", "remorseful", "remote", "repentant", "repulsive", "required", "resolute", "resonant", "respectful", "responsible", "responsive", "revolving", "rewarding", "rhetorical", "rich", "right", "righteous", "rightful", "rigid", "ringed", "ripe", "ritzy", "roasted", "robust", "romantic", "roomy", "rosy", "rotating", "rotten", "rotund", "rough", "round", "rowdy", "royal", "rubbery", "ruddy", "rude", "rundown", "runny", "rural", "rustic rusty", "ruthless"], + "s": + ["sable", "sad", "safe", "salty", "same", "sandy", "sane", "sarcastic", "sardonic", "sassy", "satisfied", "satisfying", "savory", "scaly", "scandalous", "scant", "scarce", "scared", "scary", "scattered", "scented", "scholarly", "scientific", "scintillating", "scornful", "scratchy", "scrawny", "screeching", "second", "secondary", "second-hand", "secret", "secretive", "sedate", "seemly", "selective", "self-assured", "selfish", "self-reliant", "sentimental", "separate", "serene", "serious", "serpentine", "several", "severe", "shabby", "shadowy", "shady", "shaggy", "shaky", "shallow", "shameful", "shameless", "sharp", "shimmering", "shiny", "shivering", "shocked", "shocking", "shoddy", "short", "short-term", "showy", "shrill", "shut", "shy", "sick", "silent", "silky", "silly", "silver", "similar", "simple", "simplistic", "sincere", "sinful", "single", "six", "sizzling", "skeletal", "skillful", "skinny", "sleepy", "slight", "slim", "slimy", "slippery", "sloppy", "slow", "slushy", "small", "smarmy", "smart", "smelly", "smiling", "smoggy", "smooth", "smug", "snappy", "snarling", "sneaky", "sniveling", "snobbish", "snoopy", "snotty", "sociable", "soft", "soggy", "solid", "somber", "some", "sophisticated", "sordid", "sore", "sorrowful", "soulful", "soupy", "sour", "sour", "Spanish", "sparkling", "sparse", "special", "specific", "spectacular", "speedy", "spherical", "spicy", "spiffy", "spiky", "spirited", "spiritual", "spiteful", "splendid", "spooky", "spotless", "spotted", "spotty", "spry", "spurious", "squalid", "square", "squeaky", "squealing", "squeamish", "squiggly", "stable", "staid", "stained", "staking", "stale", "standard", "standing", "starchy", "stark", "starry", "statuesque", "steadfast", "steady", "steel", "steep", "stereotyped", "sticky", "stiff", "stimulating", "stingy", "stormy", "stout", "straight", "strange", "strict", "strident", "striking", "striped", "strong", "studious", "stunning", "stunning", "stupendous", "stupid", "sturdy", "stylish", "subdued", "submissive", "subsequent", "substantial", "subtle", "suburban", "successful", "succinct", "succulent", "sudden", "sugary", "sulky", "sunny", "super", "superb", "superficial", "superior", "supportive", "supreme", "sure-footed", "surprised", "suspicious", "svelte", "swanky", "sweaty", "sweet", "sweltering", "swift", "sympathetic", "symptomatic", "synonymous"], + "t": + ["taboo", "tacit", "tacky", "talented", "talkative", "tall", "tame", "tan", "tangible", "tangy", "tart", "tasteful", "tasteless", "tasty", "tattered", "taut", "tawdry", "tearful", "tedious", "teeming", "teeny", "teeny-tiny", "telling", "temporary", "tempting", "ten", "tender", "tense", "tenuous", "tepid", "terrible", "terrific", "tested", "testy", "thankful", "that", "therapeutic", "these", "thick", "thin", "thinkable", "third", "thirsty", "this", "thorny", "thorough", "those", "thoughtful", "thoughtless", "threadbare", "threatening", "three", "thrifty", "thundering", "thunderous", "tidy", "tight", "tightfisted", "timely", "tinted", "tiny", "tired", "tiresome", "toothsome", "torn", "torpid", "total", "tough", "towering", "tragic", "trained", "tranquil", "trashy", "traumatic", "treasured", "tremendous", "triangular", "tricky", "trifling", "trim", "trite", "trivial", "troubled", "truculent", "true", "trusting", "trustworthy", "trusty", "truthful", "tubby", "turbulent", "twin", "two", "typical"], + "u": + ["ubiquitous", "ugliest", "ugly", "ultimate", "ultra", "unable", "unaccountable", "unarmed", "unaware", "unbecoming", "unbiased", "uncomfortable", "uncommon", "unconscious", "uncovered", "understated", "understood", "undesirable", "unequal", "unequaled", "uneven", "unfinished", "unfit", "unfolded", "unfortunate", "unhappy", "unhealthy", "uniform", "unimportant", "uninterested", "unique", "united", "unkempt", "unknown", "unlawful", "unlined", "unlucky", "unnatural", "unpleasant", "unrealistic", "unripe", "unruly", "unselfish", "unsightly", "unsteady", "unsuitable", "unsung", "untidy", "untimely", "untried", "untrue", "unused", "unusual", "unwelcome", "unwieldy", "unwitting", "unwritten", "upbeat", "uppity", "upright", "upset", "uptight", "urban", "usable", "used", "used", "useful", "useless", "utilized", "utopian", "utter", "uttermost"], + "v": + ["vacant", "vacuous", "vagabond", "vague", "vain", "valid", "valuable", "vapid", "variable", "various", "vast", "velvety", "venerated", "vengeful", "venomous", "verdant", "verifiable", "versed", "vexed", "vibrant", "vicious", "victorious", "vigilant", "vigorous", "villainous", "violent", "violet", "virtual", "virtuous", "visible", "vital", "vivacious", "vivid", "voiceless", "volatile", "voluminous", "voracious", "vulgar"], + "w": + ["wacky", "waggish", "waiting", "wakeful", "wan", "wandering", "wanting", "warlike", "warm", "warmhearted", "warped", "wary", "wasteful", "watchful", "waterlogged", "watery", "wavy", "weak", "wealthy", "weary", "webbed", "wee", "weekly", "weepy", "weighty", "weird", "welcome", "well-documented", "well-groomed", "well-informed", "well-lit", "well-made", "well-off", "well-to-do", "well-worn", "wet", "which", "whimsical", "whirlwind", "whispered", "whispering", "white", "whole", "wholesale", "whopping", "wicked", "wide", "wide-eyed", "wiggly", "wild", "willing", "wilted", "winding", "windy", "winged", "wiry", "wise", "wistful", "witty", "wobbly", "woebegone", "woeful", "womanly", "wonderful", "wooden", "woozy", "wordy", "workable", "worldly", "worn", "worried", "worrisome", "worse", "worst", "worthless", "worthwhile", "worthy", "wrathful", "wretched", "writhing", "wrong", "wry"], + "x": + ["xenophobic"], + "y": + ["yawning", "yearly", "yellow", "yellowish", "yielding", "young", "youthful", "yummy"], + "z": + ["zany", "zealous", "zesty", "zigzag", "zippy", "zonked"] +} \ No newline at end of file diff --git a/lib/tasks/versions/generate_release_name.rake b/lib/tasks/versions/generate_release_name.rake new file mode 100644 index 000000000..7a8d8591c --- /dev/null +++ b/lib/tasks/versions/generate_release_name.rake @@ -0,0 +1,88 @@ +namespace :versions do + desc 'Generate a new release name' + task generate_release_name: :environment do + def rand_el(arr) + arr[rand(arr.count)] + end + + # Load the data from JSON + adjectives = JSON.parse(File.read('lib/tasks/versions/adjectives.json')) + scientists = JSON.parse(File.read('lib/tasks/versions/scientists.json')) + + puts '------------------------------------' + puts '' + puts 'sciNote release name generator v0.1 ALPHA' + puts '' + puts '------------------------------------' + + puts '' + puts 'Choose what you would like to do:' + puts '1) Provide a scientist by yourself' + puts '2) Randomly choose a scientist from a pre-defined list' + res = $stdin.gets.strip + unless res.in?(['', '1', '2']) + puts 'Invalid parameter, exiting' + next + end + + # First, pick scientist name + if res.in?(['', '1']) + puts 'Enter full scientist first name (all but surname) ' \ + 'in capitalized case' + first_name = $stdin.gets.strip + puts 'Enter full scientist surname ' \ + 'in capitalized case' + last_name = $stdin.gets.strip + key = last_name[0].downcase.to_sym + full_name = "#{first_name} #{last_name}" + else + key = rand_el(scientists.keys) + full_name = rand_el(scientists[key]) + last_name = full_name.split(' ')[-1] + puts "Randomly chosen scientist: #{full_name}" + puts '' + end + + # Now, pick adjective + adjective = rand_el(adjectives[key]) + + puts '------------------------------------' + puts 'Tadaaaa!' + puts 'The new release will be named......' + puts '(waaaaait for iiiiit)' + puts '' + puts '##############################################' + puts " #{adjective.capitalize} #{last_name}" + puts " (full name: #{full_name})" + puts '##############################################' + + loop do + puts '' + puts 'What would you like to do?' + puts '(E) Exit' + puts '(a) generate new adjective' + puts '(s) generate new random scientist' + res = $stdin.gets.strip + unless res.in?(['', 'e', 'E', 'a', 'A', 's', 'S']) + puts 'Invalid parameter!' + next + end + + break if res.in?(['', 'e', 'E']) + + if res.in?(%w(s S)) + key = rand_el(scientists.keys) + full_name = rand_el(scientists[key]) + last_name = full_name.split(' ')[-1] + end + + adjective = rand_el(adjectives[key]) + + puts '' + puts '##############################################' + puts " #{adjective.capitalize} #{last_name} " + puts " (full name: #{full_name})" + puts '##############################################' + end + end +end diff --git a/lib/tasks/versions/scientists.json b/lib/tasks/versions/scientists.json new file mode 100644 index 000000000..86f7b0ca4 --- /dev/null +++ b/lib/tasks/versions/scientists.json @@ -0,0 +1,54 @@ +{ + "a": + ["Louis Agassiz", "Maria Gaetana Agnesi", "Al-Battani", "Abu Nasr Al-Farabi", "Jim Al-Khalili", "Muhammad ibn Musa al-Khwarizmi", "Mihailo Petrovic Alas", "Angel Alcala", "Salim Ali", "Luis Alvarez", "Andre Marie Ampère", "Anaximander", "Mary Anning", "Virginia Apgar", "Archimedes", "Agnes Arber", "Aristarchus", "Aristotle", "Svante Arrhenius", "Oswald Avery", "Amedeo Avogadro", "Avicenna"], + "b": + ["Charles Babbage", "Francis Bacon", "Alexander Bain", "John Logie Baird", "Joseph Banks", "Ramon Barba", "John Bardeen", "Ibn Battuta", "William Bayliss", "George Beadle", "Arnold Orville Beckman", "Henri Becquerel", "Emil Adolf Behring", "Alexander Graham Bell", "Emile Berliner", "Claude Bernard", "Timothy John Berners-Lee", "Daniel Bernoulli", "Jacob Berzelius", "Henry Bessemer", "Hans Bethe", "Homi Jehangir Bhabha", "Alfred Binet", "Clarence Birdseye", "Kristian Birkeland", "Elizabeth Blackwell", "Alfred Blalock", "Katharine Burr Blodgett", "Franz Boas", "David Bohm", "Aage Bohr", "Niels Bohr", "Ludwig Boltzmann", "Max Born", "Carl Bosch", "Robert Bosch", "Jagadish Chandra Bose", "Satyendra Nath Bose", "Walther Wilhelm Georg Bothe", "Robert Boyle", "Lawrence Bragg", "Tycho Brahe", "Brahmagupta", "Georg Brandt", "Wernher Von Braun", "Louis de Broglie", "Alexander Brongniart", "Robert Brown", "Michael E. Brown", "Lester R. Brown", "Eduard Buchner", "William Buckland", "Georges-Louis Leclerc, Comte de Buffon", "Robert Bunsen", "Luther Burbank", "Jocelyn Bell Burnell", "Thomas Burnet"], + "c": + ["Benjamin Cabrera", "Santiago Ramon y Cajal", "Rachel Carson", "George Washington Carver", "Henry Cavendish", "Anders Celsius", "James Chadwick", "Subrahmanyan Chandrasekhar", "Erwin Chargaff", "Noam Chomsky", "Steven Chu", "Leland Clark", "Arthur Compton", "Nicolaus Copernicus", "Gerty Theresa Cori", "Charles-Augustin de Coulomb", "Jacques Cousteau", "Brian Cox", "Francis Crick", "Nicholas Culpeper", "Marie Curie", "Pierre Curie", "Georges Cuvier", "Adalbert Czerny"], + "d": + ["Gottlieb Daimler", "John Dalton", "James Dwight Dana", "Charles Darwin", "Humphry Davy", "Peter Debye", "Max Delbruck", "Jean Andre Deluc", "René Descartes", "Rudolf Christian Karl Diesel", "Paul Dirac", "Prokop Divis", "Theodosius Dobzhansky", "Frank Drake", "K. Eric Drexler"], + "e": + ["Arthur Eddington", "Thomas Edison", "Paul Ehrlich", "Albert Einstein", "Gertrude Elion", "Empedocles", "Eratosthenes", "Euclid", "Leonhard Euler"], + "f": + ["Michael Faraday", "Pierre de Fermat", "Enrico Fermi", "Richard Feynman", "Fibonacci – Leonardo of Pisa", "Emil Fischer", "Ronald Fisher", "Alexander Fleming", "Henry Ford", "Lee De Forest", "Dian Fossey", "Leon Foucault", "Benjamin Franklin", "Rosalind Franklin", "Sigmund Freud"], + "g": + ["Galen", "Galileo Galilei", "Francis Galton", "Luigi Galvani", "George Gamow", "Carl Friedrich Gauss", "Murray Gell-Mann", "Sophie Germain", "Willard Gibbs", "William Gilbert", "Sheldon Lee Glashow", "Robert Goddard", "Maria Goeppert-Mayer", "Jane Goodall", "Stephen Jay Gould"], + "h": + ["Fritz Haber", "Ernst Haeckel", "Otto Hahn", "Albrecht von Haller", "Edmund Halley", "Thomas Harriot", "William Harvey", "Stephen Hawking", "Otto Haxel", "Werner Heisenberg", "Hermann von Helmholtz", "Jan Baptist von Helmont", "Joseph Henry", "William Herschel", "Gustav Ludwig Hertz", "Heinrich Hertz", "Karl F. Herzfeld", "Antony Hewish", "David Hilbert", "Maurice Hilleman", "Hipparchus", "Hippocrates", "Shintaro Hirase", "Dorothy Hodgkin", "Robert Hooke", "Frederick Gowland Hopkins", "William Hopkins", "Grace Murray Hopper", "Frank Hornby", "Jack Horner", "Bernardo Houssay", "Fred Hoyle", "Edwin Hubble", "Alexander von Humboldt", "Zora Neale Hurston", "James Hutton", "Christiaan Huygens"], + "i": + ["Ernesto Illy", "Ernst Ising", "Keisuke Ito"], + "j": + ["Mae Carol Jemison", "Edward Jenner", "J. Hans D. Jensen", "Irene Joliot-Curie", "James Prescott Joule", "Percy Lavon Julian"], + "k": + ["Michio Kaku", "Heike Kamerlingh Onnes", "Friedrich August Kekulé", "Frances Kelsey", "Pearl Kendrick", "Johannes Kepler", "Abdul Qadeer Khan", "Omar Khayyam", "Alfred Kinsey", "Gustav Kirchoff", "Robert Koch", "Emil Kraepelin", "Thomas Kuhn", "Stephanie Kwolek"], + "l": + ["Jean-Baptiste Lamarck", "Hedy Lamarr", "Edwin Herbert Land", "Karl Landsteiner", "Pierre-Simon Laplace", "Max von Laue", "Antoine Lavoisier", "Ernest Lawrence", "Henrietta Leavitt", "Antonie van Leeuwenhoek", "Inge Lehmann", "Gottfried Leibniz", "Georges Lemaître", "Leonardo da Vinci", "Niccolo Leoniceno", "Aldo Leopold", "Rita Levi-Montalcini", "Claude Levi-Strauss", "Willard Frank Libby", "Justus von Liebig", "Carolus Linnaeus", "Joseph Lister", "John Locke", "Hendrik Antoon Lorentz", "Konrad Lorenz", "Ada Lovelace", "Lucretius", "Charles Lyell", "Trofim Lysenko"], + "m": + ["Ernst Mach", "Marcello Malpighi", "Jane Marcet", "Guglielmo Marconi", "Lynn Margulis", "James Clerk Maxwell", "Ernst Mayr", "Barbara McClintock", "Lise Meitner", "Gregor Mendel", "Dmitri Mendeleev", "Franz Mesmer", "Antonio Meucci", "Albert Abraham Michelson", "Thomas Midgeley Jr.", "Maria Mitchell", "Mario Molina", "Thomas Hunt Morgan", "Henry Moseley"], + "n": + ["Ukichiro Nakaya", "John Napier", "John Needham", "John von Neumann", "Thomas Newcomen", "Isaac Newton", "Florence Nightingale", "Tim Noakes", "Alfred Nobel", "Emmy Noether", "Christiane Nusslein-Volhard", "Bill Nye"], + "o": + ["Hans Christian Oersted", "Georg Ohm", "J. Robert Oppenheimer", "Wilhelm Ostwald"], + "p": + ["Blaise Pascal", "Louis Pasteur", "Wolfgang Ernst Pauli", "Linus Pauling", "Randy Pausch", "Ivan Pavlov", "Marguerite Perey", "Jean Piaget", "Philippe Pinel", "Max Planck", "Pliny the Elder", "Karl Popper", "Beatrix Potter", "Joseph Priestley", "Claudius Ptolemy", "Pythagoras"], + "q": + ["Harriet Quimby", "Thabit ibn Qurra"], + "r": + ["C. V. Raman", "Srinivasa Ramanujan", "William Ramsay", "John Ray", "Prafulla Chandra Ray", "Francesco Redi", "Sally Ride", "Bernhard Riemann", "Wilhelm Röntgen", "Hermann Rorschach", "Ronald Ross", "Ibn Rushd", "Ernest Rutherford"], + "s": + ["Carl Sagan", "Mohammad Abdus Salam", "Jonas Salk", "Frederick Sanger", "Alberto Santos-Dumont", "Walter Schottky", "Erwin Schrödinger", "Theodor Schwann", "Glenn Seaborg", "Hans Selye", "Charles Sherrington", "Gene Shoemaker", "Ernst Werner von Siemens", "George Gaylord Simpson", "B. F. Skinner", "William Smith", "Frederick Soddy", "Arnold Sommerfeld", "Nettie Stevens", "William John Swainson", "Leo Szilard"], + "t": + ["Niccolo Tartaglia", "Edward Teller", "Nikola Tesla", "Thales of Miletus", "Benjamin Thompson", "J. J. Thomson", "William Thomson", "Henry David Thoreau", "Kip S. Thorne", "Clyde Tombaugh", "Evangelista Torricelli", "Charles Townes", "Alan Turing", "Neil deGrasse Tyson"], + "u": + ["Harold Urey"], + "v": + ["Craig Venter", "Vladimir Vernadsky", "Andreas Vesalius", "Rudolf Virchow", "Artturi Virtanen", "Alessandro Volta"], + "w": + ["George Wald", "Alfred Russel Wallace", "James Watson", "James Watt", "Alfred Wegener", "John Archibald Wheeler", "Maurice Wilkins", "Thomas Willis", "E. O. Wilson", "Sven Wingqvist", "Sergei Winogradsky", "Friedrich Wöhler", "Wilbur and Orville Wright", "Wilhelm Wundt"], + "x": + [], + "y": + ["Chen-Ning Yang"], + "z": + ["Ahmed Zewail"] +} \ No newline at end of file From 8e999e673a4008741d70230da30217b269fd9ce8 Mon Sep 17 00:00:00 2001 From: Luka Murn Date: Wed, 23 Aug 2017 08:40:47 +0200 Subject: [PATCH 12/24] Remove scinote-web.tgz from index --- scinote-web-v1.0.0.tgz | Bin 23258 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 scinote-web-v1.0.0.tgz diff --git a/scinote-web-v1.0.0.tgz b/scinote-web-v1.0.0.tgz deleted file mode 100644 index 289870cc3256cd95766a2e77eddad30c733a856d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23258 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

sCves%HyF`-(k`7CVG6B0cS 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 U^JzZK=RQCGKU)njX8>RV0NuAJ$^ZZW From afa05c8c1407cde16b2c394b64ec3195b62f64ad Mon Sep 17 00:00:00 2001 From: zmagod Date: Wed, 23 Aug 2017 17:10:45 +0200 Subject: [PATCH 13/24] fixed background worker in dev env --- Makefile | 2 +- config/environments/development.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index bc41aaeee..cc886509b 100644 --- a/Makefile +++ b/Makefile @@ -66,7 +66,7 @@ stop: @docker-compose stop worker: - @$(MAKE) rails cmd="rake jobs:work" + @$(MAKE) rails cmd="rake jobs:work export WORKER=1" cli: @$(MAKE) rails cmd="/bin/bash" diff --git a/config/environments/development.rb b/config/environments/development.rb index e4d01050d..e8cf8a048 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -4,10 +4,10 @@ Rails.application.configure do # In the development environment your application's code is reloaded on # every request. This slows down response time but is perfect for development # since you don't have to restart the web server when you make code changes. - config.cache_classes = true + config.cache_classes = ENV['WORKER'] ? true : false # Do not eager load code on boot. - config.eager_load = true + config.eager_load = ENV['WORKER'] ? true : false # Show full error reports and disable caching. config.consider_all_requests_local = true From 0e14420193d400ae6223d8e03114df75b368ac04 Mon Sep 17 00:00:00 2001 From: Mojca Lorber Date: Wed, 6 Sep 2017 14:41:14 +0200 Subject: [PATCH 14/24] fix bugs with importing samples --- app/models/team.rb | 4 ++-- app/views/samples/_parse_samples_modal.html.erb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/models/team.rb b/app/models/team.rb index 72164fcf9..04a45375a 100644 --- a/app/models/team.rb +++ b/app/models/team.rb @@ -106,7 +106,7 @@ class Team < ActiveRecord::Base sheet.row(i).each.with_index do |value, index| if index == stype_index - stype = SampleType.where(name: value, team: self).take + stype = SampleType.where(name: value.strip, team: self).take unless stype stype = SampleType.new(name: value, team: self) @@ -117,7 +117,7 @@ class Team < ActiveRecord::Base end sample.sample_type = stype elsif index == sgroup_index - sgroup = SampleGroup.where(name: value, team: self).take + sgroup = SampleGroup.where(name: value.strip, team: self).take unless sgroup sgroup = SampleGroup.new(name: value, team: self) diff --git a/app/views/samples/_parse_samples_modal.html.erb b/app/views/samples/_parse_samples_modal.html.erb index 613c3d444..3e48a3f3c 100644 --- a/app/views/samples/_parse_samples_modal.html.erb +++ b/app/views/samples/_parse_samples_modal.html.erb @@ -28,7 +28,7 @@ <% if th.nil? %> <%= t('samples.modal_import.no_header_name') %> <% else %> - <% if th.length > Constants::NAME_TRUNCATION_LENGTH_DROPDOWN %> + <% if th.to_s.length > Constants::NAME_TRUNCATION_LENGTH_DROPDOWN %>

From 28cb9643d95f9c9506a275b07a47632f7d39596a Mon Sep 17 00:00:00 2001 From: Luka Murn Date: Thu, 14 Sep 2017 13:10:36 +0200 Subject: [PATCH 15/24] Blank new team page with breadcrumbs --- app/javascript/src/config/locales/messages.js | 1 + app/javascript/src/config/routes.js | 3 +- .../src/scenes/SettingsPage/index.jsx | 5 ++- .../scenes/SettingsPage/scenes/team/index.jsx | 22 +++++++----- .../teams/components/TeamsPageDetails.jsx | 14 ++++---- .../SettingsPage/scenes/teams/index.jsx | 19 ++++------- .../SettingsPage/scenes/teams/new/index.jsx | 34 +++++++++++++++++++ 7 files changed, 68 insertions(+), 30 deletions(-) create mode 100644 app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx diff --git a/app/javascript/src/config/locales/messages.js b/app/javascript/src/config/locales/messages.js index a2b7ada18..93ea60a3f 100644 --- a/app/javascript/src/config/locales/messages.js +++ b/app/javascript/src/config/locales/messages.js @@ -22,6 +22,7 @@ export default { }, settings_page: { all_teams: "All teams", + new_team: "New team", in_team: "You are member of {num} team", in_teams: "You are member of {num} team", leave_team: "Leave team", diff --git a/app/javascript/src/config/routes.js b/app/javascript/src/config/routes.js index 5311dccb9..e25f55853 100644 --- a/app/javascript/src/config/routes.js +++ b/app/javascript/src/config/routes.js @@ -4,5 +4,6 @@ export const ROOT_PATH = "/"; // Settings page export const SETTINGS_TEAMS_ROUTE = "/settings/teams"; export const SETTINGS_TEAM_ROUTE = "/settings/teams/:id"; +export const SETTINGS_NEW_TEAM_ROUTE = "/settings/teams/new"; export const SETTINGS_ACCOUNT_PROFILE = "/settings/account/profile"; -export const SETTINGS_ACCOUNT_PREFERENCES = "/settings/account/preferences"; +export const SETTINGS_ACCOUNT_PREFERENCES = "/settings/account/preferences"; \ No newline at end of file diff --git a/app/javascript/src/scenes/SettingsPage/index.jsx b/app/javascript/src/scenes/SettingsPage/index.jsx index 389954d88..62ab771a8 100644 --- a/app/javascript/src/scenes/SettingsPage/index.jsx +++ b/app/javascript/src/scenes/SettingsPage/index.jsx @@ -8,7 +8,8 @@ import { ROOT_PATH, SETTINGS_TEAMS_ROUTE, SETTINGS_TEAM_ROUTE, - SETTINGS_ACCOUNT_PROFILE + SETTINGS_ACCOUNT_PROFILE, + SETTINGS_NEW_TEAM_ROUTE } from "../../config/routes"; import { @@ -21,6 +22,7 @@ import NotFound from "../../components/404/NotFound"; import SettingsAccount from "./scenes/account/SettingsAccount"; import SettingsTeams from "./scenes/teams"; import SettingsTeam from "./scenes/team"; +import SettingsNewTeam from "./scenes/teams/new"; export default class SettingsPage extends Component { constructor(props) { @@ -70,6 +72,7 @@ export default class SettingsPage extends Component { component={SettingsAccount} />} /> + - -
  • - + + + - -
  • -
  • + + + {this.state.team.name} -
  • -
    + + {this.state.team.name} diff --git a/app/javascript/src/scenes/SettingsPage/scenes/teams/components/TeamsPageDetails.jsx b/app/javascript/src/scenes/SettingsPage/scenes/teams/components/TeamsPageDetails.jsx index a31b94959..83341dca1 100644 --- a/app/javascript/src/scenes/SettingsPage/scenes/teams/components/TeamsPageDetails.jsx +++ b/app/javascript/src/scenes/SettingsPage/scenes/teams/components/TeamsPageDetails.jsx @@ -1,8 +1,10 @@ import React from "react"; +import { LinkContainer } from "react-router-bootstrap"; import PropTypes, { number, string, bool } from "prop-types"; import styled from "styled-components"; import { FormattedMessage, FormattedPlural } from "react-intl"; import { Button, Glyphicon } from "react-bootstrap"; +import { SETTINGS_NEW_TEAM_ROUTE } from "../../../../../app/dom_routes"; const Wrapper = styled.div`margin: 15px 0;`; const TeamsPageDetails = ({ teams }) => { @@ -28,13 +30,11 @@ const TeamsPageDetails = ({ teams }) => { /> } />  - + + + ); }; diff --git a/app/javascript/src/scenes/SettingsPage/scenes/teams/index.jsx b/app/javascript/src/scenes/SettingsPage/scenes/teams/index.jsx index a1dc27dce..0ab25b844 100644 --- a/app/javascript/src/scenes/SettingsPage/scenes/teams/index.jsx +++ b/app/javascript/src/scenes/SettingsPage/scenes/teams/index.jsx @@ -1,13 +1,11 @@ import React from "react"; import PropTypes, { number, string, bool } from "prop-types"; import styled from "styled-components"; +import { Breadcrumb } from "react-bootstrap"; import { connect } from "react-redux"; import { FormattedMessage } from "react-intl"; -import { - BORDER_LIGHT_COLOR, - COLOR_CONCRETE -} from "../../../../config/constants/colors"; +import { BORDER_LIGHT_COLOR } from "../../../../config/constants/colors"; import TeamsPageDetails from "./components/TeamsPageDetails"; import TeamsDataTable from "./components/TeamsDataTable"; @@ -21,16 +19,13 @@ const Wrapper = styled.div` padding: 16px 15px 50px 15px; `; -const TabTitle = styled.div` - background-color: ${COLOR_CONCRETE}; - padding: 15px; -`; - const SettingsTeams = ({ teams }) => - - - + + + + + ; diff --git a/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx b/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx new file mode 100644 index 000000000..23579be73 --- /dev/null +++ b/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx @@ -0,0 +1,34 @@ +import React, { Component } from "react"; +import styled from "styled-components"; +import { Breadcrumb } from "react-bootstrap"; +import { LinkContainer } from "react-router-bootstrap"; +import { FormattedMessage } from "react-intl"; +import { SETTINGS_TEAMS_ROUTE } from "../../../../../config/routes"; + +import { BORDER_LIGHT_COLOR } from "../../../../../config/constants/colors"; + +const Wrapper = styled.div` + background: white; + box-sizing: border-box; + border: 1px solid ${BORDER_LIGHT_COLOR}; + border-top: none; + margin: 0; + padding: 16px 15px 50px 15px; +`; + +const SettingsNewTeam = () => + + + + + + + + + + + + TODO + ; + +export default SettingsNewTeam; \ No newline at end of file From 0108d9ea1993509c2cbed74824d5bfb09fee6a9b Mon Sep 17 00:00:00 2001 From: Luka Murn Date: Fri, 15 Sep 2017 10:34:36 +0200 Subject: [PATCH 16/24] Finish new team GUI --- .../teams/new/components/NameFormControl.jsx | 21 +++++++++ app/javascript/src/config/locales/messages.js | 10 ++++- .../SettingsPage/scenes/teams/new/index.jsx | 43 +++++++++++++++++-- 3 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 app/javascript/packs/src/settings/components/teams/new/components/NameFormControl.jsx diff --git a/app/javascript/packs/src/settings/components/teams/new/components/NameFormControl.jsx b/app/javascript/packs/src/settings/components/teams/new/components/NameFormControl.jsx new file mode 100644 index 000000000..37c0541ad --- /dev/null +++ b/app/javascript/packs/src/settings/components/teams/new/components/NameFormControl.jsx @@ -0,0 +1,21 @@ +import React from "react"; +import PropTypes from "prop-types"; +import {defineMessages, injectIntl, intlShape} from 'react-intl'; +import { FormControl } from "react-bootstrap"; + +const messages = defineMessages({ + placeholder: { id: "settings_page.new_team.name_placeholder" } +}); + +const NameFormControl = ({intl}) => + ; + +NameFormControl.PropTypes = { + intl: intlShape.isRequired +}; + +export default injectIntl(NameFormControl); diff --git a/app/javascript/src/config/locales/messages.js b/app/javascript/src/config/locales/messages.js index 93ea60a3f..c17319fb7 100644 --- a/app/javascript/src/config/locales/messages.js +++ b/app/javascript/src/config/locales/messages.js @@ -22,7 +22,6 @@ export default { }, settings_page: { all_teams: "All teams", - new_team: "New team", in_team: "You are member of {num} team", in_teams: "You are member of {num} team", leave_team: "Leave team", @@ -102,6 +101,15 @@ export default { administrator: "Administrator", remove_user: "Remove" } + }, + new_team: { + title: "New team", + name_label: "Team name", + name_placeholder: "My team", + name_sublabel: "Pick a name that would best describe your team (e.g. 'University of ..., Department of ...').", + description_label: "Description", + description_sublabel: "Describe your team.", + create: "Create team" } }, activities: { diff --git a/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx b/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx index 23579be73..5b5e84f40 100644 --- a/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx +++ b/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx @@ -1,12 +1,14 @@ -import React, { Component } from "react"; +import React from "react"; import styled from "styled-components"; -import { Breadcrumb } from "react-bootstrap"; +import { Breadcrumb, FormGroup, FormControl, ControlLabel, HelpBlock, Button } from "react-bootstrap"; import { LinkContainer } from "react-router-bootstrap"; import { FormattedMessage } from "react-intl"; import { SETTINGS_TEAMS_ROUTE } from "../../../../../config/routes"; import { BORDER_LIGHT_COLOR } from "../../../../../config/constants/colors"; +import NameFormControl from "./components/NameFormControl"; + const Wrapper = styled.div` background: white; box-sizing: border-box; @@ -25,10 +27,43 @@ const SettingsNewTeam = () => - + - TODO + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ; export default SettingsNewTeam; \ No newline at end of file From df44976fc6abbbc7ce2d55b999d545a3a8fd3c0a Mon Sep 17 00:00:00 2001 From: Luka Murn Date: Fri, 15 Sep 2017 16:00:15 +0200 Subject: [PATCH 17/24] Save input values into component state --- .../teams/new/components/NameFormControl.jsx | 3 +- app/javascript/src/config/api_endpoints.js | 1 + .../src/config/constants/numeric.js | 3 +- app/javascript/src/config/locales/messages.js | 1 + .../SettingsPage/scenes/teams/new/index.jsx | 211 ++++++++++++++---- package.json | 1 + yarn.lock | 8 +- 7 files changed, 181 insertions(+), 47 deletions(-) diff --git a/app/javascript/packs/src/settings/components/teams/new/components/NameFormControl.jsx b/app/javascript/packs/src/settings/components/teams/new/components/NameFormControl.jsx index 37c0541ad..4bfea4456 100644 --- a/app/javascript/packs/src/settings/components/teams/new/components/NameFormControl.jsx +++ b/app/javascript/packs/src/settings/components/teams/new/components/NameFormControl.jsx @@ -7,11 +7,12 @@ const messages = defineMessages({ placeholder: { id: "settings_page.new_team.name_placeholder" } }); -const NameFormControl = ({intl}) => +const NameFormControl = ({ intl, ...props }) => ; NameFormControl.PropTypes = { diff --git a/app/javascript/src/config/api_endpoints.js b/app/javascript/src/config/api_endpoints.js index b0837e8d6..6b243daef 100644 --- a/app/javascript/src/config/api_endpoints.js +++ b/app/javascript/src/config/api_endpoints.js @@ -11,6 +11,7 @@ export const SETTINGS_ACCOUNT_PREFERENCES_PATH = // teams export const TEAMS_PATH = "/client_api/teams"; +export const TEAMS_NEW_PATH = "/client_api/teams/new"; export const CHANGE_TEAM_PATH = "/client_api/teams/change_team"; export const TEAM_DETAILS_PATH = "/client_api/teams/:team_id/details"; export const TEAM_UPDATE_PATH = "/client_api/teams/update"; diff --git a/app/javascript/src/config/constants/numeric.js b/app/javascript/src/config/constants/numeric.js index 1ed90ac4d..601d72a10 100644 --- a/app/javascript/src/config/constants/numeric.js +++ b/app/javascript/src/config/constants/numeric.js @@ -1,3 +1,4 @@ export const ENTER_KEY_CODE = 13; -export const TEXT_MAX_LENGTH = 10000; +export const NAME_MIN_LENGTH = 2; export const NAME_MAX_LENGTH = 255; +export const TEXT_MAX_LENGTH = 10000; diff --git a/app/javascript/src/config/locales/messages.js b/app/javascript/src/config/locales/messages.js index c17319fb7..798c7bebd 100644 --- a/app/javascript/src/config/locales/messages.js +++ b/app/javascript/src/config/locales/messages.js @@ -8,6 +8,7 @@ export default { loading: "Loading ..." }, error_messages: { + text_too_short: "is too short (minimum is {min_length} characters)", text_too_long: "is too long (maximum is {max_length} characters)" }, navbar: { diff --git a/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx b/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx index 5b5e84f40..b4c4f64df 100644 --- a/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx +++ b/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx @@ -1,9 +1,17 @@ -import React from "react"; +import React, { Component } from "react"; +import update from "immutability-helper"; import styled from "styled-components"; +import axios from "../../../../../app/axios"; import { Breadcrumb, FormGroup, FormControl, ControlLabel, HelpBlock, Button } from "react-bootstrap"; import { LinkContainer } from "react-router-bootstrap"; import { FormattedMessage } from "react-intl"; import { SETTINGS_TEAMS_ROUTE } from "../../../../../config/routes"; +import { TEAMS_NEW_PATH } from "../../../../../config/api_endpoints"; +import { + NAME_MIN_LENGTH, + NAME_MAX_LENGTH, + TEXT_MAX_LENGTH +} from "../../../../../config/constants/numeric"; import { BORDER_LIGHT_COLOR } from "../../../../../config/constants/colors"; @@ -18,52 +26,167 @@ const Wrapper = styled.div` padding: 16px 15px 50px 15px; `; -const SettingsNewTeam = () => - - - - - - - - - - - +class SettingsNewTeam extends Component { + constructor(props) { + super(props); + this.state = { + team: { + name: { + value: "", + errorMessage: "", + }, + description: { + value: "", + errorMessage: "", + } + } + }; -
    + this.getValidationState = this.getValidationState.bind(this); + this.validateField = this.validateField.bind(this); + this.handleChange = this.handleChange.bind(this); + this.onSubmit = this.onSubmit.bind(this); + } - - - - - - - - - - + getValidationState(attr) { + if (this.state.team[attr].errorMessage.length > 0) { + return "error"; + } + return null; + } - - - - - - - - - - + validateField(key, value) { + let errorMessage; + if (key === "name") { + errorMessage = ""; - - - - -
    -
    ; + if (value.length < NAME_MIN_LENGTH) { + errorMessage = ; + } else if (value.length > NAME_MAX_LENGTH) { + errorMessage = ; + } + + this.newState = update( + this.newState, + { team: { name: { errorMessage: { $set: errorMessage } } } } + ); + } else if (key === "description") { + errorMessage = ""; + + if (value.length > TEXT_MAX_LENGTH) { + errorMessage = ; + } + + this.newState = update( + this.newState, + { team: { description: { errorMessage: { $set: errorMessage } } } } + ); + } + } + + handleChange(e) { + const key = e.target.name; + const value = e.target.value; + + this.newState = { ...this.state }; + + // Update value in the state + this.newState = update( + this.newState, + { team: { [key]: { value: { $set: value } } } } + ); + + // Validate the input + this.validateField(key, value); + + // Refresh state + this.setState(this.newState); + } + + onSubmit() { + axios({ + method: "post", + url: TEAMS_NEW_PATH, + withCredentials: true, + data: { team: this.state.team } + }) + .then(response => { + // TODO: Redirect to team page + }) + .catch(error => this.setState({ errorMessage: error.message })); + } + + render() { + return ( + + + + + + + + + + + + +
    + + + + + + + + {this.state.team.name.errorMessage} + + + + +
    +
    + + + + + + + + {this.state.team.description.errorMessage} + + + + +
    +
    + + + + + +
    +
    + ); + } +} export default SettingsNewTeam; \ No newline at end of file diff --git a/package.json b/package.json index ad2c953f7..0371cd7c3 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "extract-text-webpack-plugin": "^3.0.0", "file-loader": "^0.11.2", "glob": "^7.1.2", + "immutability-helper": "^2.3.0", "js-yaml": "^3.9.0", "lodash": "^4.17.4", "moment": "^2.18.1", diff --git a/yarn.lock b/yarn.lock index 9e8f9b798..c0ce92ca1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2756,6 +2756,12 @@ ignore@^3.2.0: version "3.3.3" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.3.tgz#432352e57accd87ab3110e82d3fea0e47812156d" +immutability-helper@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/immutability-helper/-/immutability-helper-2.3.1.tgz#8ccfce92157208c120b2afad7ed05c11114c086e" + dependencies: + invariant "^2.2.0" + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -2845,7 +2851,7 @@ intl-relativeformat@^1.3.0: dependencies: intl-messageformat "1.3.0" -invariant@^2.0.0, invariant@^2.1.0, invariant@^2.1.1, invariant@^2.2.1, invariant@^2.2.2: +invariant@^2.0.0, invariant@^2.1.0, invariant@^2.1.1, invariant@^2.2.0, invariant@^2.2.1, invariant@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" dependencies: From 80c05e50ec23dda401be2531d4ecfe24dd4c0be6 Mon Sep 17 00:00:00 2001 From: Luka Murn Date: Mon, 18 Sep 2017 09:13:37 +0200 Subject: [PATCH 18/24] Semi-working version of create new team form --- .../client_api/teams/teams_controller.rb | 29 ++++--- app/javascript/src/config/api_endpoints.js | 2 +- .../SettingsPage/scenes/teams/new/index.jsx | 76 +++++++++++-------- app/services/client_api/teams_service.rb | 42 ++++++++-- config/routes.rb | 2 + 5 files changed, 103 insertions(+), 48 deletions(-) diff --git a/app/controllers/client_api/teams/teams_controller.rb b/app/controllers/client_api/teams/teams_controller.rb index e97e03daa..dca1c0a88 100644 --- a/app/controllers/client_api/teams/teams_controller.rb +++ b/app/controllers/client_api/teams/teams_controller.rb @@ -8,31 +8,42 @@ module ClientApi teams: current_user.teams_data) end + def new; end + + def create + teams_service = ClientApi::TeamsService.new(current_user: current_user, + params: team_params) + teams_service.create_team! + success_response('/client_api/teams/index', teams_service.teams_data) + rescue ClientApi::CustomTeamError => error + error_response(error.to_s) + end + def details - team_service = ClientApi::TeamsService.new(team_id: params[:team_id], + teams_service = ClientApi::TeamsService.new(team_id: params[:team_id], current_user: current_user) success_response('/client_api/teams/details', - team_service.team_page_details_data) + teams_service.team_page_details_data) rescue ClientApi::CustomTeamError error_response end def change_team - team_service = ClientApi::TeamsService.new(team_id: params[:team_id], + teams_service = ClientApi::TeamsService.new(team_id: params[:team_id], current_user: current_user) - team_service.change_current_team! - success_response('/client_api/teams/index', team_service.teams_data) + teams_service.change_current_team! + success_response('/client_api/teams/index', teams_service.teams_data) rescue ClientApi::CustomTeamError error_response end def update - team_service = ClientApi::TeamsService.new(team_id: params[:team_id], + teams_service = ClientApi::TeamsService.new(team_id: params[:team_id], current_user: current_user, params: team_params) - team_service.update_team! + teams_service.update_team! success_response('/client_api/teams/update_details', - team_service.single_team_details_data) + teams_service.single_team_details_data) rescue ClientApi::CustomTeamError => error error_response(error.to_s) end @@ -40,7 +51,7 @@ module ClientApi private def team_params - params.require(:team).permit(:description, :name) + params.require(:team).permit(:name, :description) end def success_response(template, locals) diff --git a/app/javascript/src/config/api_endpoints.js b/app/javascript/src/config/api_endpoints.js index 6b243daef..ae5c3693e 100644 --- a/app/javascript/src/config/api_endpoints.js +++ b/app/javascript/src/config/api_endpoints.js @@ -11,7 +11,7 @@ export const SETTINGS_ACCOUNT_PREFERENCES_PATH = // teams export const TEAMS_PATH = "/client_api/teams"; -export const TEAMS_NEW_PATH = "/client_api/teams/new"; +export const TEAMS_NEW_PATH = "/client_api/teams"; export const CHANGE_TEAM_PATH = "/client_api/teams/change_team"; export const TEAM_DETAILS_PATH = "/client_api/teams/:team_id/details"; export const TEAM_UPDATE_PATH = "/client_api/teams/update"; diff --git a/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx b/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx index b4c4f64df..cb2905075 100644 --- a/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx +++ b/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx @@ -1,10 +1,11 @@ import React, { Component } from "react"; -import update from "immutability-helper"; -import styled from "styled-components"; -import axios from "../../../../../app/axios"; import { Breadcrumb, FormGroup, FormControl, ControlLabel, HelpBlock, Button } from "react-bootstrap"; +import { Redirect } from "react-router"; import { LinkContainer } from "react-router-bootstrap"; import { FormattedMessage } from "react-intl"; +import update from "immutability-helper"; +import styled from "styled-components"; +import axios from "../../../../../config/axios"; import { SETTINGS_TEAMS_ROUTE } from "../../../../../config/routes"; import { TEAMS_NEW_PATH } from "../../../../../config/api_endpoints"; import { @@ -31,15 +32,14 @@ class SettingsNewTeam extends Component { super(props); this.state = { team: { - name: { - value: "", - errorMessage: "", - }, - description: { - value: "", - errorMessage: "", - } - } + name: "", + description: "", + }, + errorMessages: { + name: "", + description: "" + }, + formSuccess: false }; this.getValidationState = this.getValidationState.bind(this); @@ -48,8 +48,27 @@ class SettingsNewTeam extends Component { this.onSubmit = this.onSubmit.bind(this); } + onSubmit() { + axios({ + method: "post", + url: TEAMS_NEW_PATH, + withCredentials: true, + data: { team: this.state.team } + }) + .then(response => { + // Redirect back to teams page + this.newState = { ...this.state }; + this.newState = update( + this.newState, + { formSuccess: { $set: true } } + ); + this.setState(this.newState); + }) + .catch(error => this.setState({ errorMessage: error.message })); // TODO: Generic error message + } + getValidationState(attr) { - if (this.state.team[attr].errorMessage.length > 0) { + if (this.state.errorMessages[attr].length > 0) { return "error"; } return null; @@ -68,7 +87,7 @@ class SettingsNewTeam extends Component { this.newState = update( this.newState, - { team: { name: { errorMessage: { $set: errorMessage } } } } + { errorMessages: { name: { $set: errorMessage } } } ); } else if (key === "description") { errorMessage = ""; @@ -79,7 +98,7 @@ class SettingsNewTeam extends Component { this.newState = update( this.newState, - { team: { description: { errorMessage: { $set: errorMessage } } } } + { errorMessages: { description: { $set: errorMessage } } } ); } } @@ -93,7 +112,7 @@ class SettingsNewTeam extends Component { // Update value in the state this.newState = update( this.newState, - { team: { [key]: { value: { $set: value } } } } + { team: { [key]: { $set: value } } } ); // Validate the input @@ -103,20 +122,11 @@ class SettingsNewTeam extends Component { this.setState(this.newState); } - onSubmit() { - axios({ - method: "post", - url: TEAMS_NEW_PATH, - withCredentials: true, - data: { team: this.state.team } - }) - .then(response => { - // TODO: Redirect to team page - }) - .catch(error => this.setState({ errorMessage: error.message })); - } - render() { + if (this.state.formSuccess) { + return ; + } + return ( @@ -140,12 +150,12 @@ class SettingsNewTeam extends Component { - {this.state.team.name.errorMessage} + {this.state.errorMessages.name} @@ -162,12 +172,12 @@ class SettingsNewTeam extends Component { - {this.state.team.description.errorMessage} + {this.state.errorMessages.description} diff --git a/app/services/client_api/teams_service.rb b/app/services/client_api/teams_service.rb index e62dbd226..7664b97a4 100644 --- a/app/services/client_api/teams_service.rb +++ b/app/services/client_api/teams_service.rb @@ -1,11 +1,42 @@ +require 'aspector' + module ClientApi class TeamsService def initialize(arg) - team_id = arg.fetch(:team_id) { raise ClientApi::CustomTeamError } - @params = arg.fetch(:params) { false } - @team = Team.find_by_id(team_id) - @user = arg.fetch(:current_user) { raise ClientApi::CustomTeamError } - raise ClientApi::CustomTeamError unless @user.teams.include? @team + @arg = arg || {} + @params = @arg.fetch(:params) { false } + @user = @arg.fetch(:current_user) { raise ClientApi::CustomTeamError } + end + + aspector do + before %w( + change_current_team! + team_page_details_data + single_team_details_data + update_team! + teams_data + ) do + team_id = @arg.fetch(:team_id) { raise ClientApi::CustomTeamError } + @team = Team.find_by_id(team_id) + raise ClientApi::CustomTeamError unless @user.teams.include? @team + end + end + + def create_team! + @team = Team.new(@params) + @team.created_by = @user + + if @team.save + # Okay, team is created, now + # add the current user as admin + UserTeam.create( + user: @user, + team: @team, + role: 2 + ) + else + raise ClientApi::CustomTeamError, @team.errors.full_messages + end end def change_current_team! @@ -34,5 +65,6 @@ module ClientApi { teams: @user.teams_data } end end + CustomTeamError = Class.new(StandardError) end diff --git a/config/routes.rb b/config/routes.rb index 7e595a242..398e374e7 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -19,7 +19,9 @@ Rails.application.routes.draw do # teams get '/teams', to: 'teams/teams#index' namespace :teams do + get '/new', to: 'teams#new' get '/:team_id/details', to: 'teams#details' + post '/', to: 'teams#create' post '/change_team', to: 'teams#change_team' post '/update', to: 'teams#update' end From 44877a13a54791584f6fe8bae73b1a6ef897b122 Mon Sep 17 00:00:00 2001 From: Luka Murn Date: Tue, 19 Sep 2017 10:37:21 +0200 Subject: [PATCH 19/24] Refactor services on backend. New team page is now working --- .../client_api/teams/teams_controller.rb | 65 +++++--- .../SettingsPage/scenes/teams/new/index.jsx | 144 +++++++++++------- app/services/client_api/base_service.rb | 27 ++++ .../client_api/teams/create_service.rb | 26 ++++ app/services/client_api/teams_service.rb | 40 +---- 5 files changed, 194 insertions(+), 108 deletions(-) create mode 100644 app/services/client_api/base_service.rb create mode 100644 app/services/client_api/teams/create_service.rb diff --git a/app/controllers/client_api/teams/teams_controller.rb b/app/controllers/client_api/teams/teams_controller.rb index dca1c0a88..2e73148ba 100644 --- a/app/controllers/client_api/teams/teams_controller.rb +++ b/app/controllers/client_api/teams/teams_controller.rb @@ -4,26 +4,34 @@ module ClientApi include ClientApi::Users::UserTeamsHelper def index - success_response('/client_api/teams/index', - teams: current_user.teams_data) + success_response(template: '/client_api/teams/index', + locals: { teams: current_user.teams_data }) end def new; end def create - teams_service = ClientApi::TeamsService.new(current_user: current_user, - params: team_params) - teams_service.create_team! - success_response('/client_api/teams/index', teams_service.teams_data) - rescue ClientApi::CustomTeamError => error - error_response(error.to_s) + service = ClientApi::Teams::CreateService.new( + current_user: current_user, + params: team_params + ) + result = service.execute + + if result[:status] == :success + success_response(details: { id: service.team.id }) + else + error_response( + message: result[:message], + details: service.team.errors + ) + end end def details teams_service = ClientApi::TeamsService.new(team_id: params[:team_id], current_user: current_user) - success_response('/client_api/teams/details', - teams_service.team_page_details_data) + success_response(template: '/client_api/teams/details', + locals: teams_service.team_page_details_data) rescue ClientApi::CustomTeamError error_response end @@ -32,7 +40,8 @@ module ClientApi teams_service = ClientApi::TeamsService.new(team_id: params[:team_id], current_user: current_user) teams_service.change_current_team! - success_response('/client_api/teams/index', teams_service.teams_data) + success_response(template: '/client_api/teams/index', + locals: teams_service.teams_data) rescue ClientApi::CustomTeamError error_response end @@ -42,10 +51,10 @@ module ClientApi current_user: current_user, params: team_params) teams_service.update_team! - success_response('/client_api/teams/update_details', - teams_service.single_team_details_data) + success_response(template: '/client_api/teams/update_details', + locals: teams_service.single_team_details_data) rescue ClientApi::CustomTeamError => error - error_response(error.to_s) + error_response(message: error.to_s) end private @@ -54,20 +63,36 @@ module ClientApi params.require(:team).permit(:name, :description) end - def success_response(template, locals) + def success_response(args = {}) + template = args.fetch(:template) { nil } + locals = args.fetch(:locals) { {} } + details = args.fetch(:details) { {} } + respond_to do |format| format.json do - render template: template, - status: :ok, - locals: locals + if template + render template: template, + status: :ok, + locals: locals + else + render json: { details: details }, status: :ok + end end end end - def error_response(message = t('client_api.generic_error_message')) + def error_response(args) + message = args.fetch(:message) { t('client_api.generic_error_message') } + details = args.fetch(:details) { {} } + status = args.fetch(:status) { :unprocessable_entity } + respond_to do |format| format.json do - render json: { message: message }, status: :unprocessable_entity + render json: { + message: message, + details: details + }, + status: status end end end diff --git a/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx b/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx index cb2905075..3ea30a5d7 100644 --- a/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx +++ b/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx @@ -6,7 +6,11 @@ import { FormattedMessage } from "react-intl"; import update from "immutability-helper"; import styled from "styled-components"; import axios from "../../../../../config/axios"; -import { SETTINGS_TEAMS_ROUTE } from "../../../../../config/routes"; +import _ from "lodash"; +import { + SETTINGS_TEAMS_ROUTE, + SETTINGS_TEAM_ROUTE +} from "../../../../../config/routes"; import { TEAMS_NEW_PATH } from "../../../../../config/api_endpoints"; import { NAME_MIN_LENGTH, @@ -35,43 +39,54 @@ class SettingsNewTeam extends Component { name: "", description: "", }, - errorMessages: { + formErrors: { name: "", description: "" }, - formSuccess: false + redirectTo: "" }; - this.getValidationState = this.getValidationState.bind(this); + this.onSubmit = this.onSubmit.bind(this); this.validateField = this.validateField.bind(this); this.handleChange = this.handleChange.bind(this); - this.onSubmit = this.onSubmit.bind(this); + this.renderTeamNameFormGroup = this.renderTeamNameFormGroup.bind(this); + this.renderTeamDescriptionFormGroup = this.renderTeamDescriptionFormGroup.bind(this); } - onSubmit() { + onSubmit(e) { + e.preventDefault(); + axios({ method: "post", url: TEAMS_NEW_PATH, withCredentials: true, data: { team: this.state.team } }) - .then(response => { - // Redirect back to teams page + .then(sr => { + // Redirect to the new team page this.newState = { ...this.state }; this.newState = update( this.newState, - { formSuccess: { $set: true } } + { redirectTo: { + $set: SETTINGS_TEAM_ROUTE.replace(':id', sr.data.details.id) + } + } ); this.setState(this.newState); }) - .catch(error => this.setState({ errorMessage: error.message })); // TODO: Generic error message - } - - getValidationState(attr) { - if (this.state.errorMessages[attr].length > 0) { - return "error"; - } - return null; + .catch(er => { + // Display errors + this.newState = { ...this.state }; + ['name', 'description'].forEach((el) => { + if (er.response.data.details[el]) { + this.newState = update( + this.newState, + { formErrors: { name: { $set: {er.response.data.details[el]} } } } + ); + } + }); + this.setState(this.newState); + }); } validateField(key, value) { @@ -87,7 +102,7 @@ class SettingsNewTeam extends Component { this.newState = update( this.newState, - { errorMessages: { name: { $set: errorMessage } } } + { formErrors: { name: { $set: errorMessage } } } ); } else if (key === "description") { errorMessage = ""; @@ -98,7 +113,7 @@ class SettingsNewTeam extends Component { this.newState = update( this.newState, - { errorMessages: { description: { $set: errorMessage } } } + { formErrors: { description: { $set: errorMessage } } } ); } } @@ -122,11 +137,62 @@ class SettingsNewTeam extends Component { this.setState(this.newState); } + renderTeamNameFormGroup() { + const formGroupClass = this.state.formErrors.name ? "form-group has-error" : "form-group"; + const validationState = this.state.formErrors.name ? "error" : null; + return ( + + + + + + + {this.state.formErrors.name} + + ); + } + + renderTeamDescriptionFormGroup() { + const formGroupClass = this.state.formErrors.description ? "form-group has-error" : "form-group"; + const validationState = this.state.formErrors.description ? "error" : null; + return ( + + + + + + + {this.state.formErrors.description} + + ); + } + render() { - if (this.state.formSuccess) { - return ; + // Redirect if form successful + if (!_.isEmpty(this.state.redirectTo)) { + return ; } + const btnDisabled = !_.isEmpty(this.state.formErrors.name) || + !_.isEmpty(this.state.formErrors.description); + return ( @@ -142,43 +208,14 @@ class SettingsNewTeam extends Component {
    - - - - - - - {this.state.errorMessages.name} - + {this.renderTeamNameFormGroup()}

    - - - - - - - {this.state.errorMessages.description} - + {this.renderTeamDescriptionFormGroup()} @@ -190,9 +227,10 @@ class SettingsNewTeam extends Component { - +
    ); diff --git a/app/services/client_api/base_service.rb b/app/services/client_api/base_service.rb new file mode 100644 index 000000000..377932264 --- /dev/null +++ b/app/services/client_api/base_service.rb @@ -0,0 +1,27 @@ +module ClientApi + class BaseService + attr_accessor :current_user, :params + + def initialize(args) + @current_user = args.fetch(:current_user) { raise StandardError } + @params = (args.fetch(:params) { {} }).dup + end + + private + + def error(message, http_status = nil) + result = { + message: message, + status: :error + } + + result[:http_status] = http_status if http_status + result + end + + def success(pass_back = {}) + pass_back[:status] = :success + pass_back + end + end +end diff --git a/app/services/client_api/teams/create_service.rb b/app/services/client_api/teams/create_service.rb new file mode 100644 index 000000000..bc75feec0 --- /dev/null +++ b/app/services/client_api/teams/create_service.rb @@ -0,0 +1,26 @@ +module ClientApi + module Teams + class CreateService < BaseService + attr_accessor :team + + def execute + @team = Team.new(@params) + @team.created_by = @user + + if @team.save + # Okay, team is created, now + # add the current user as admin + UserTeam.create( + user: @user, + team: @team, + role: 2 + ) + + success + else + error(@team.errors.full_messages.uniq.join('. ')) + end + end + end + end +end diff --git a/app/services/client_api/teams_service.rb b/app/services/client_api/teams_service.rb index 7664b97a4..82f533428 100644 --- a/app/services/client_api/teams_service.rb +++ b/app/services/client_api/teams_service.rb @@ -1,42 +1,12 @@ -require 'aspector' - module ClientApi class TeamsService def initialize(arg) - @arg = arg || {} - @params = @arg.fetch(:params) { false } - @user = @arg.fetch(:current_user) { raise ClientApi::CustomTeamError } - end + @params = arg.fetch(:params) { false } + @user = arg.fetch(:current_user) { raise ClientApi::CustomTeamError } - aspector do - before %w( - change_current_team! - team_page_details_data - single_team_details_data - update_team! - teams_data - ) do - team_id = @arg.fetch(:team_id) { raise ClientApi::CustomTeamError } - @team = Team.find_by_id(team_id) - raise ClientApi::CustomTeamError unless @user.teams.include? @team - end - end - - def create_team! - @team = Team.new(@params) - @team.created_by = @user - - if @team.save - # Okay, team is created, now - # add the current user as admin - UserTeam.create( - user: @user, - team: @team, - role: 2 - ) - else - raise ClientApi::CustomTeamError, @team.errors.full_messages - end + team_id = arg.fetch(:team_id) { raise ClientApi::CustomTeamError } + @team = Team.find_by_id(team_id) + raise ClientApi::CustomTeamError unless @user.teams.include? @team end def change_current_team! From decdce17fa61282122357e00add4b3af085456d0 Mon Sep 17 00:00:00 2001 From: Luka Murn Date: Tue, 19 Sep 2017 16:47:55 +0200 Subject: [PATCH 20/24] Fix rebasing problems --- app/javascript/src/scenes/SettingsPage/scenes/team/index.jsx | 5 +---- .../scenes/teams/components/TeamsPageDetails.jsx | 2 +- .../scenes}/teams/new/components/NameFormControl.jsx | 0 3 files changed, 2 insertions(+), 5 deletions(-) rename app/javascript/{packs/src/settings/components => src/scenes/SettingsPage/scenes}/teams/new/components/NameFormControl.jsx (100%) diff --git a/app/javascript/src/scenes/SettingsPage/scenes/team/index.jsx b/app/javascript/src/scenes/SettingsPage/scenes/team/index.jsx index 4ef011b13..61d5e1c02 100644 --- a/app/javascript/src/scenes/SettingsPage/scenes/team/index.jsx +++ b/app/javascript/src/scenes/SettingsPage/scenes/team/index.jsx @@ -1,6 +1,5 @@ import React, { Component } from "react"; import ReactRouterPropTypes from "react-router-prop-types"; -import { Link } from "react-router-dom"; import styled from "styled-components"; import { Breadcrumb, Row, Col, Glyphicon, Well } from "react-bootstrap"; import { LinkContainer } from "react-router-bootstrap"; @@ -10,10 +9,8 @@ import prettysize from "prettysize"; import axios from "../../../../config/axios"; import { SETTINGS_TEAMS_ROUTE } from "../../../../config/routes"; -import { TEAM_DETAILS_PATH, SETTINGS_TEAMS } from "../../../../config/api_endpoints"; +import { TEAM_DETAILS_PATH } from "../../../../config/api_endpoints"; import { BORDER_LIGHT_COLOR } from "../../../../config/constants/colors"; -import { SETTINGS_TEAMS_ROUTE } from "../../../../app/dom_routes"; -import { TEAM_DETAILS_PATH } from "../../../../app/routes"; import TeamsMembers from "./components/TeamsMembers"; import UpdateTeamDescriptionModal from "./components/UpdateTeamDescriptionModal"; diff --git a/app/javascript/src/scenes/SettingsPage/scenes/teams/components/TeamsPageDetails.jsx b/app/javascript/src/scenes/SettingsPage/scenes/teams/components/TeamsPageDetails.jsx index 83341dca1..36033786d 100644 --- a/app/javascript/src/scenes/SettingsPage/scenes/teams/components/TeamsPageDetails.jsx +++ b/app/javascript/src/scenes/SettingsPage/scenes/teams/components/TeamsPageDetails.jsx @@ -4,7 +4,7 @@ import PropTypes, { number, string, bool } from "prop-types"; import styled from "styled-components"; import { FormattedMessage, FormattedPlural } from "react-intl"; import { Button, Glyphicon } from "react-bootstrap"; -import { SETTINGS_NEW_TEAM_ROUTE } from "../../../../../app/dom_routes"; +import { SETTINGS_NEW_TEAM_ROUTE } from "../../../../../config/routes"; const Wrapper = styled.div`margin: 15px 0;`; const TeamsPageDetails = ({ teams }) => { diff --git a/app/javascript/packs/src/settings/components/teams/new/components/NameFormControl.jsx b/app/javascript/src/scenes/SettingsPage/scenes/teams/new/components/NameFormControl.jsx similarity index 100% rename from app/javascript/packs/src/settings/components/teams/new/components/NameFormControl.jsx rename to app/javascript/src/scenes/SettingsPage/scenes/teams/new/components/NameFormControl.jsx From 869c3593a3353973a24c6d840d845232a58267e5 Mon Sep 17 00:00:00 2001 From: Luka Murn Date: Tue, 19 Sep 2017 16:56:39 +0200 Subject: [PATCH 21/24] Hound is love, Hound is life --- .../scenes/teams/new/components/NameFormControl.jsx | 3 +-- .../src/scenes/SettingsPage/scenes/teams/new/index.jsx | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/javascript/src/scenes/SettingsPage/scenes/teams/new/components/NameFormControl.jsx b/app/javascript/src/scenes/SettingsPage/scenes/teams/new/components/NameFormControl.jsx index 4bfea4456..d7737c06a 100644 --- a/app/javascript/src/scenes/SettingsPage/scenes/teams/new/components/NameFormControl.jsx +++ b/app/javascript/src/scenes/SettingsPage/scenes/teams/new/components/NameFormControl.jsx @@ -1,5 +1,4 @@ import React from "react"; -import PropTypes from "prop-types"; import {defineMessages, injectIntl, intlShape} from 'react-intl'; import { FormControl } from "react-bootstrap"; @@ -15,7 +14,7 @@ const NameFormControl = ({ intl, ...props }) => {...props} />; -NameFormControl.PropTypes = { +NameFormControl.propTypes = { intl: intlShape.isRequired }; diff --git a/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx b/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx index 3ea30a5d7..a446cffd4 100644 --- a/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx +++ b/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx @@ -5,8 +5,8 @@ import { LinkContainer } from "react-router-bootstrap"; import { FormattedMessage } from "react-intl"; import update from "immutability-helper"; import styled from "styled-components"; -import axios from "../../../../../config/axios"; import _ from "lodash"; +import axios from "../../../../../config/axios"; import { SETTINGS_TEAMS_ROUTE, SETTINGS_TEAM_ROUTE From 6e993f41b8e33ee9892985378018643c2bd04a52 Mon Sep 17 00:00:00 2001 From: Luka Murn Date: Tue, 19 Sep 2017 16:59:19 +0200 Subject: [PATCH 22/24] Indentation error --- .../scenes/teams/new/components/NameFormControl.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/src/scenes/SettingsPage/scenes/teams/new/components/NameFormControl.jsx b/app/javascript/src/scenes/SettingsPage/scenes/teams/new/components/NameFormControl.jsx index d7737c06a..cb82deab0 100644 --- a/app/javascript/src/scenes/SettingsPage/scenes/teams/new/components/NameFormControl.jsx +++ b/app/javascript/src/scenes/SettingsPage/scenes/teams/new/components/NameFormControl.jsx @@ -15,7 +15,7 @@ const NameFormControl = ({ intl, ...props }) => />; NameFormControl.propTypes = { - intl: intlShape.isRequired + intl: intlShape.isRequired }; export default injectIntl(NameFormControl); From 416ccf905db6e5ad8b1aa05ef0a855b260c18757 Mon Sep 17 00:00:00 2001 From: Luka Murn Date: Wed, 20 Sep 2017 10:53:38 +0200 Subject: [PATCH 23/24] Minor fix --- app/controllers/client_api/teams/teams_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/client_api/teams/teams_controller.rb b/app/controllers/client_api/teams/teams_controller.rb index 2e73148ba..7ed25f78a 100644 --- a/app/controllers/client_api/teams/teams_controller.rb +++ b/app/controllers/client_api/teams/teams_controller.rb @@ -81,7 +81,7 @@ module ClientApi end end - def error_response(args) + def error_response(args = {}) message = args.fetch(:message) { t('client_api.generic_error_message') } details = args.fetch(:details) { {} } status = args.fetch(:status) { :unprocessable_entity } From 5429f6bbbd84576246eec274c2e698892f7d4137 Mon Sep 17 00:00:00 2001 From: Luka Murn Date: Thu, 21 Sep 2017 08:06:11 +0200 Subject: [PATCH 24/24] Fix @ZmagoD's remarks --- .../client_api/teams/teams_controller.rb | 2 -- .../SettingsPage/scenes/teams/new/index.jsx | 28 +++++++++++-------- .../client_api/teams/create_service.rb | 4 +-- app/services/client_api/teams_service.rb | 1 - 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/app/controllers/client_api/teams/teams_controller.rb b/app/controllers/client_api/teams/teams_controller.rb index 7ed25f78a..9d3fdfc02 100644 --- a/app/controllers/client_api/teams/teams_controller.rb +++ b/app/controllers/client_api/teams/teams_controller.rb @@ -8,8 +8,6 @@ module ClientApi locals: { teams: current_user.teams_data }) end - def new; end - def create service = ClientApi::Teams::CreateService.new( current_user: current_user, diff --git a/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx b/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx index a446cffd4..c7478385f 100644 --- a/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx +++ b/app/javascript/src/scenes/SettingsPage/scenes/teams/new/index.jsx @@ -31,6 +31,10 @@ const Wrapper = styled.div` padding: 16px 15px 50px 15px; `; +const MyFormGroupDiv = styled.div` + margin-bottom: 15px; +`; + class SettingsNewTeam extends Component { constructor(props) { super(props); @@ -208,19 +212,19 @@ class SettingsNewTeam extends Component {
    - {this.renderTeamNameFormGroup()} - - - -
    -
    + + {this.renderTeamNameFormGroup()} + + + + - {this.renderTeamDescriptionFormGroup()} - - - -
    -
    + + {this.renderTeamDescriptionFormGroup()} + + + +