├── .bowerrc ├── .dockerignore ├── .editorconfig ├── .env-example ├── .gitignore ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── app ├── .htaccess ├── AppCache.php ├── AppKernel.php ├── DoctrineMigrations │ ├── Version20170701083607.php │ ├── Version20170701083839.php │ ├── Version20170907000538.php │ ├── Version20170914142257.php │ ├── Version20170915083636.php │ ├── Version20170918155155.php │ ├── Version20170930124648.php │ ├── Version20170930171444.php │ ├── Version20171003083933.php │ └── Version20171004065248.php ├── Resources │ ├── FOSUserBundle │ │ └── views │ │ │ ├── ChangePassword │ │ │ ├── change_password.html.twig │ │ │ └── change_password_content.html.twig │ │ │ ├── Profile │ │ │ ├── edit.html.twig │ │ │ ├── edit_content.html.twig │ │ │ ├── show.html.twig │ │ │ └── show_content.html.twig │ │ │ ├── Registration │ │ │ ├── check_email.html.twig │ │ │ ├── confirmed.html.twig │ │ │ ├── email.txt.twig │ │ │ ├── register.html.twig │ │ │ └── register_content.html.twig │ │ │ ├── Resetting │ │ │ ├── check_email.html.twig │ │ │ ├── email.txt.twig │ │ │ ├── request.html.twig │ │ │ ├── request_content.html.twig │ │ │ ├── reset.html.twig │ │ │ └── reset_content.html.twig │ │ │ ├── Security │ │ │ ├── login.html.twig │ │ │ └── login_content.html.twig │ │ │ └── layout.html.twig │ ├── translations │ │ └── dashboard.id.xlf │ └── views │ │ ├── area │ │ ├── create.html.twig │ │ ├── edit.html.twig │ │ ├── index.html.twig │ │ └── show.html.twig │ │ ├── base.html.twig │ │ ├── dashboard │ │ └── index.html.twig │ │ ├── device │ │ ├── areas.html.twig │ │ ├── create.html.twig │ │ ├── index.html.twig │ │ ├── resources.html.twig │ │ └── show.html.twig │ │ ├── field │ │ ├── add.html.twig │ │ ├── index.html.twig │ │ └── show.html.twig │ │ ├── inventory │ │ └── index.html.twig │ │ ├── navbar.html.twig │ │ ├── plant │ │ ├── create.html.twig │ │ ├── edit.html.twig │ │ ├── harvest.html.twig │ │ ├── index.html.twig │ │ └── show.html.twig │ │ ├── reservoir │ │ ├── index.html.twig │ │ └── show.html.twig │ │ ├── right-sidebar.html.twig │ │ ├── seed │ │ ├── create.html.twig │ │ └── edit.html.twig │ │ ├── settings │ │ └── index.html.twig │ │ ├── sidebar.html.twig │ │ └── task │ │ ├── create.html.twig │ │ ├── index.html.twig │ │ └── show.html.twig └── config │ ├── config.yml │ ├── config_dev.yml │ ├── config_prod.yml │ ├── config_test.yml │ ├── repository.yml │ ├── routing.yml │ ├── routing_dev.yml │ ├── security.yml │ └── services.yml ├── bin ├── console └── symfony_requirements ├── bower.json ├── composer.json ├── composer.lock ├── docker-compose.dev.yml ├── docker-compose.yml ├── docker └── app │ ├── Dockerfile │ ├── nginx.conf │ └── tania-entrypoint ├── phpunit.xml.dist ├── readme-assets ├── project-dashboard.jpg └── project-logo.png ├── src ├── .htaccess └── AppBundle │ ├── AppBundle.php │ ├── Controller │ ├── AreaController.php │ ├── DashboardController.php │ ├── DeviceController.php │ ├── FieldController.php │ ├── InventoryController.php │ ├── PlantController.php │ ├── ProfileController.php │ ├── RegistrationController.php │ ├── ReservoirController.php │ ├── SettingsController.php │ └── TaskController.php │ ├── Data │ ├── CategoryMaster.php │ └── CountryList.php │ ├── DataFixtures │ └── ORM │ │ ├── LoadResourceData.php │ │ ├── LoadSeedCategory.php │ │ └── LoadUserData.php │ ├── DoctrineExtensions │ └── Utils │ │ └── AnyValue.php │ ├── Entity │ ├── Area.php │ ├── AreasDevices.php │ ├── Device.php │ ├── Field.php │ ├── Plant.php │ ├── Reservoir.php │ ├── Resource.php │ ├── ResourcesDevices.php │ ├── Seed.php │ ├── SeedCategory.php │ ├── Setting.php │ ├── Task.php │ └── User.php │ ├── Form │ ├── AreaDeviceType.php │ ├── AreaType.php │ ├── DeviceType.php │ ├── FieldType.php │ ├── PlantHarvestType.php │ ├── PlantType.php │ ├── RegistrationFormType.php │ ├── ReservoirType.php │ ├── ResourceDeviceType.php │ ├── SeedType.php │ ├── SettingType.php │ └── TaskType.php │ └── Repository │ ├── AbstractRepository.php │ ├── PlantRepository.php │ └── TaskRepository.php ├── tests └── AppBundle │ └── Controller │ ├── AreaControllerTest.php │ ├── DashboardControllerTest.php │ ├── DeviceControllerTest.php │ ├── FieldControllerTest.php │ ├── InventoryControllerTest.php │ ├── PlantControllerTest.php │ ├── ReservoirControllerTest.php │ └── TaskControllerTest.php ├── var ├── SymfonyRequirements.php ├── cache │ └── .gitkeep ├── logs │ └── .gitkeep └── sessions │ └── .gitkeep ├── web.config └── web ├── .htaccess ├── app.php ├── apple-touch-icon.png ├── assets ├── css │ ├── .DS_Store │ ├── bootstrap-theme.css │ ├── bootstrap-theme.min.css │ ├── bootstrap.css │ ├── bootstrap.min.css │ ├── material-design-icons │ │ ├── css │ │ │ ├── material-design-iconic-font.css │ │ │ └── material-design-iconic-font.min.css │ │ ├── fonts │ │ │ ├── Material-Design-Iconic-Font.eot │ │ │ ├── Material-Design-Iconic-Font.svg │ │ │ ├── Material-Design-Iconic-Font.ttf │ │ │ ├── Material-Design-Iconic-Font.woff │ │ │ └── Material-Design-Iconic-Font.woff2 │ │ └── less │ │ │ ├── aliases.less │ │ │ ├── border.less │ │ │ ├── core.less │ │ │ ├── fixed-width.less │ │ │ ├── icons.less │ │ │ ├── list.less │ │ │ ├── material-design-iconic-font.less │ │ │ ├── path.less │ │ │ ├── pulled.less │ │ │ ├── rotated.less │ │ │ ├── sizes.less │ │ │ ├── spinned.less │ │ │ ├── stacked.less │ │ │ └── variables.less │ ├── non-responsive.css │ ├── select2.min.css │ ├── style.css │ ├── style.min.css │ └── tania.css ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 ├── img │ ├── favicon.png │ ├── logo.png │ ├── plant-basil.jpg │ └── tania.png ├── js │ ├── area.js │ ├── bootstrap.js │ ├── bootstrap.min.js │ ├── dashboard.js │ ├── field-map-show.js │ ├── field-map.js │ ├── jquery-ui │ │ └── jquery-ui.min.js │ ├── jquery.min.js │ ├── js-cookie.js │ ├── main.js │ ├── npm.js │ ├── paho-mqtt.js │ ├── perfect-scrollbar │ │ ├── perfect-scrollbar.jquery.js │ │ ├── perfect-scrollbar.jquery.min.js │ │ ├── perfect-scrollbar.js │ │ └── perfect-scrollbar.min.js │ ├── plant.js │ └── task.js └── lib │ ├── .DS_Store │ └── roboto │ ├── Roboto-Black.eot │ ├── Roboto-Black.svg │ ├── Roboto-Black.ttf │ ├── Roboto-Black.woff │ ├── Roboto-Black.woff2 │ ├── Roboto-BlackItalic.eot │ ├── Roboto-BlackItalic.svg │ ├── Roboto-BlackItalic.ttf │ ├── Roboto-BlackItalic.woff │ ├── Roboto-BlackItalic.woff2 │ ├── Roboto-Bold.eot │ ├── Roboto-Bold.svg │ ├── Roboto-Bold.ttf │ ├── Roboto-Bold.woff │ ├── Roboto-Bold.woff2 │ ├── Roboto-BoldItalic.eot │ ├── Roboto-BoldItalic.svg │ ├── Roboto-BoldItalic.ttf │ ├── Roboto-BoldItalic.woff │ ├── Roboto-BoldItalic.woff2 │ ├── Roboto-Light.eot │ ├── Roboto-Light.svg │ ├── Roboto-Light.ttf │ ├── Roboto-Light.woff │ ├── Roboto-Light.woff2 │ ├── Roboto-LightItalic.eot │ ├── Roboto-LightItalic.svg │ ├── Roboto-LightItalic.ttf │ ├── Roboto-LightItalic.woff │ ├── Roboto-LightItalic.woff2 │ ├── Roboto-Medium.eot │ ├── Roboto-Medium.svg │ ├── Roboto-Medium.ttf │ ├── Roboto-Medium.woff │ ├── Roboto-Medium.woff2 │ ├── Roboto-MediumItalic.eot │ ├── Roboto-MediumItalic.svg │ ├── Roboto-MediumItalic.ttf │ ├── Roboto-MediumItalic.woff │ ├── Roboto-MediumItalic.woff2 │ ├── Roboto-Regular.eot │ ├── Roboto-Regular.svg │ ├── Roboto-Regular.ttf │ ├── Roboto-Regular.woff │ ├── Roboto-Regular.woff2 │ ├── Roboto-RegularItalic.eot │ ├── Roboto-RegularItalic.svg │ ├── Roboto-RegularItalic.ttf │ ├── Roboto-RegularItalic.woff │ ├── Roboto-RegularItalic.woff2 │ ├── Roboto-Thin.eot │ ├── Roboto-Thin.svg │ ├── Roboto-Thin.ttf │ ├── Roboto-Thin.woff │ ├── Roboto-Thin.woff2 │ ├── Roboto-ThinItalic.eot │ ├── Roboto-ThinItalic.svg │ ├── Roboto-ThinItalic.ttf │ ├── Roboto-ThinItalic.woff │ └── Roboto-ThinItalic.woff2 ├── config.php ├── debug.html ├── favicon.ico ├── robots.txt └── uploads ├── areas └── index.html ├── fields └── index.html └── seeds └── index.html /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "web/vendor" 3 | } 4 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | /.web-server-pid 2 | /app/config/parameters.yml 3 | /build/ 4 | /phpunit.xml 5 | /var/* 6 | !/var/cache 7 | /var/cache/* 8 | !var/cache/.gitkeep 9 | !/var/logs 10 | /var/logs/* 11 | !var/logs/.gitkeep 12 | !/var/sessions 13 | /var/sessions/* 14 | !var/sessions/.gitkeep 15 | !var/SymfonyRequirements.php 16 | /vendor/ 17 | /web/bundles/ 18 | /web/uploads/areas/*.png 19 | /web/uploads/areas/*.jpg 20 | /web/uploads/areas/*.gif 21 | /web/uploads/fields/*.png 22 | /web/uploads/fields/*.jpg 23 | /web/uploads/fields/*.gif 24 | /web/uploads/seeds/*.png 25 | /web/uploads/seeds/*.jpg 26 | /web/uploads/seeds/*.gif 27 | /web/uploads/areas/*.PNG 28 | /web/uploads/areas/*.JPG 29 | /web/uploads/areas/*.GIF 30 | /web/uploads/fields/*.PNG 31 | /web/uploads/fields/*.JPG 32 | /web/uploads/fields/*.GIF 33 | /web/uploads/seeds/*.PNG 34 | /web/uploads/seeds/*.JPG 35 | /web/uploads/seeds/*.GIF 36 | # Swap 37 | [._]*.s[a-v][a-z] 38 | [._]*.sw[a-p] 39 | [._]s[a-v][a-z] 40 | [._]sw[a-p] 41 | 42 | # Session 43 | Session.vim 44 | 45 | # Temporary 46 | .netrwhist 47 | *~ 48 | # Auto-generated tag files 49 | tags 50 | 51 | .DS_Store 52 | docker/**/Dockerfile 53 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | indent_style = space 8 | indent_size = 4 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.env-example: -------------------------------------------------------------------------------- 1 | #use 'en' for English and 'id' for Indonesia 2 | SYMFONY_LOCALE=en 3 | 4 | SYMFONY_SECRET=changewithyoursecretkey 5 | SYMFONY_ENV=dev 6 | 7 | #use '' instead of null if you want to empty the value 8 | SYMFONY_DB_HOST=127.0.0.1 9 | SYMFONY_DB_PORT=3306 10 | SYMFONY_DB_NAME=yourdatabasename 11 | SYMFONY_DB_USERNAME=yourdatabaseusername 12 | SYMFONY_DB_PASSWORD=yourdatabasepassword 13 | 14 | #use this default value if you don't have any mailer system 15 | SYMFONY_MAILER_TRANSPORT=smtp 16 | SYMFONY_MAILER_HOST=127.0.0.1 17 | SYMFONY_MAILER_USERNAME=admin 18 | SYMFONY_MAILER_PASSWORD=admin 19 | SYMFONY_MAILER_FROM_ADDRESS=youremail@yourdomain.com 20 | SYMFONY_MAILER_SENDER_NAME=yourname -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.web-server-pid 2 | /app/config/parameters.yml 3 | /build/ 4 | /phpunit.xml 5 | /var/* 6 | !/var/cache 7 | /var/cache/* 8 | !var/cache/.gitkeep 9 | !/var/logs 10 | /var/logs/* 11 | !var/logs/.gitkeep 12 | !/var/sessions 13 | /var/sessions/* 14 | !var/sessions/.gitkeep 15 | !var/SymfonyRequirements.php 16 | /vendor/ 17 | /web/bundles/ 18 | /web/uploads/areas/*.png 19 | /web/uploads/areas/*.jpg 20 | /web/uploads/areas/*.gif 21 | /web/uploads/fields/*.png 22 | /web/uploads/fields/*.jpg 23 | /web/uploads/fields/*.gif 24 | /web/uploads/seeds/*.png 25 | /web/uploads/seeds/*.jpg 26 | /web/uploads/seeds/*.gif 27 | /web/uploads/areas/*.PNG 28 | /web/uploads/areas/*.JPG 29 | /web/uploads/areas/*.GIF 30 | /web/uploads/fields/*.PNG 31 | /web/uploads/fields/*.JPG 32 | /web/uploads/fields/*.GIF 33 | /web/uploads/seeds/*.PNG 34 | /web/uploads/seeds/*.JPG 35 | /web/uploads/seeds/*.GIF 36 | /web/vendor/* 37 | .env 38 | composer.phar 39 | # Swap 40 | [._]*.s[a-v][a-z] 41 | [._]*.sw[a-p] 42 | [._]s[a-v][a-z] 43 | [._]sw[a-p] 44 | 45 | # Session 46 | Session.vim 47 | 48 | # Temporary 49 | .netrwhist 50 | *~ 51 | # Auto-generated tag files 52 | tags 53 | 54 | .DS_Store 55 | 56 | docker-compose.override.yml 57 | .vscode 58 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | dist: trusty 4 | 5 | sudo: required 6 | 7 | env: 8 | global: 9 | SYMFONY_LOCALE=en 10 | SYMFONY_SECRET=xCqnuwqgU7h151 11 | SYMFONY_ENV=test 12 | SYMFONY_DB_HOST=127.0.0.1 13 | SYMFONY_DB_PORT=3306 14 | SYMFONY_DB_NAME=tania_test 15 | SYMFONY_DB_USERNAME=root 16 | SYMFONY_DB_PASSWORD='' 17 | SYMFONY_MAILER_TRANSPORT=smtp 18 | SYMFONY_MAILER_HOST=127.0.0.1 19 | SYMFONY_MAILER_USERNAME=admin 20 | SYMFONY_MAILER_PASSWORD=admin 21 | SYMFONY_MAILER_FROM_ADDRESS=youremail@yourdomain.com 22 | SYMFONY_MAILER_SENDER_NAME=yourname 23 | 24 | cache: 25 | directories: 26 | - $HOME/.composer/cache/files 27 | 28 | php: 29 | - '7.1' 30 | 31 | before_install: 32 | - mysql -e 'CREATE DATABASE tania_test' 33 | 34 | install: 35 | - composer install --no-interaction 36 | - php bin/console --no-interaction doctrine:migrations:migrate --env=test 37 | - php bin/console --no-interaction doctrine:fixtures:load -n --env=test 38 | 39 | script: 40 | - ./vendor/bin/phpunit 41 | 42 | after_success: 43 | - docker build -t tanibox/tania -f docker/app/Dockerfile --build-arg BUILD_DATE="$(date +%Y-%m-%d)" . 44 | 45 | branches: 46 | only: 47 | - development 48 | 49 | services: 50 | - mysql 51 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [asep@tanibox.com](mailto:asep@tanibox.com). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Tania 2 | 3 | Hello fellow contributors, we would like to thank you for taking the time to contribute! 4 | 5 | The following is a set of guidelines for contributing to Tania, which are hosted in the [Tanibox Organization](https://github.com/tanibox) on GitHub. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request. 6 | 7 | #### Table Of Contents 8 | 9 | [Code of Conduct](#code-of-conduct) 10 | 11 | [What should I know before I get started?](#what-should-i-know-before-i-get-started) 12 | 13 | [How Can I Contribute?](#how-can-i-contribute) 14 | * [Reporting Bugs](#reporting-bugs) 15 | * [Suggesting Enhancements](#suggesting-enhancements) 16 | * [Pull Requests](#pull-requests) 17 | 18 | ## Code of Conduct 19 | 20 | This project and everyone participating in it is governed by the [Tania Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to [asep@tanibox.com](mailto:asep@tanibox.com). 21 | 22 | ## What should I know before I get started? 23 | 24 | Always use English to communicate. Don't be shy with your English because nobody is perfect. 25 | 26 | ## How Can I Contribute? 27 | 28 | ### Reporting Bugs 29 | 30 | To report bugs, you can use [our JIRA issue tracker](https://gettania.atlassian.net). Explain the detail about how can you get the bug, your environment, or anything that can help the maintainers to reproduce it. 31 | 32 | ### Suggesting Enhancements 33 | 34 | You can use [our JIRA issue tracker](https://gettania.atlassian.net) to suggest your enhancements proposal. We encourage you to join to our [Gitter](https://gitter.im/taniafarm/Lobby) also if you want to discuss your enhancements directly with the maintainers. 35 | 36 | ### Pull Requests 37 | 38 | Never ever send your pull requests to the `master` branch. Always send it to the `development` branch. Don't forget to give a clear PR subject and explain what are you changing on the description. 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # End Official Support and Maintenance for Tania PHP 2 | 3 | As the rewrite of Tania from PHP to Go is completed, and we have released the new Tania project to the public repository. The support for Tania PHP is ended. Please, check the new project at [tania-core](https://github.com/Tanibox/tania-core). 4 | 5 | ![Tania](readme-assets/project-logo.png "Tania Logo") 6 | 7 | [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/taniafarm/Lobby) 8 | [![Build Status](https://travis-ci.org/Tanibox/tania.svg?branch=development)](https://travis-ci.org/Tanibox/tania) 9 | 10 | Tania is a free and open source farming management system for everyone. You can manage your growing areas, reservoirs, farm tasks, inventories, and the crop growing progress. 11 | 12 | It is developed on top of Symfony PHP web framework. 13 | 14 | To get the stable release, you can checkout to the `master` branch or from the [release tab](https://github.com/Tanibox/tania/releases). 15 | 16 | ## Screenshots 17 | 18 | ![Tania Dashboard](https://s3-ap-southeast-1.amazonaws.com/asepco/iot-dashboard.PNG "Tania Dashboard") 19 | 20 | ## Requirements 21 | 22 | - PHP >= 7.0 23 | - MySQL >= 5.6 24 | - Composer (you can install from [getcomposer.org](http://getcomposer.org)) 25 | 26 | ## General installation steps 27 | 28 | First, clone this project: 29 | 30 | ``` 31 | git clone git@github.com:Tanibox/tania.git 32 | cd tania 33 | ``` 34 | 35 | Second, setup your database and mailer parameters in `/.env`. You can duplicate and rename the `/.env-example` file. 36 | 37 | Third, setup the web application: 38 | 39 | ``` 40 | curl -sS https://getcomposer.org/installer | php 41 | php composer.phar install 42 | ``` 43 | 44 | Fourth, setup the database tables: 45 | 46 | ``` 47 | php bin/console --no-interaction doctrine:migrations:migrate 48 | ``` 49 | 50 | Fifth, create user: 51 | 52 | ``` 53 | php bin/console fos:user:create {{user}} {{email}} {{password}} 54 | ``` 55 | 56 | The last, you can run Tania in development mode (on your PC or laptop) by using this command: 57 | 58 | ``` 59 | php bin/console server:run 60 | ``` 61 | 62 | Tania will run on `http://localhost:8000`. 63 | 64 | You can also run Tania in production mode (on your server) by referring to this [Symfony documentation](http://symfony.com/doc/current/setup/web_server_configuration.html). 65 | 66 | Done! You can start to use Tania. 67 | 68 | ## Questions and issues 69 | 70 | You can use [our JIRA issue tracker](https://gettania.atlassian.net) for bug reporting, feature request, and general feedback. 71 | 72 | ## Maintainers 73 | 74 | Current maintainers: 75 | 76 | - Asep Bagja Priandana - [Linkedin](https://www.linkedin.com/in/asepbagja/) 77 | - Retno Ika Safitri - [Linkedin](https://www.linkedin.com/in/retnoika/) 78 | - Didiet Noor - [Linkedin](https://www.linkedin.com/in/didiet/) 79 | 80 | If you are interested in being a core contributor to this project, please drop me an email at __asep@tanibox.com__. 81 | 82 | ## License 83 | 84 | Tania is available under Apache 2.0 open source license. 85 | -------------------------------------------------------------------------------- /app/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | Require all denied 3 | 4 | 5 | Order deny,allow 6 | Deny from all 7 | 8 | -------------------------------------------------------------------------------- /app/AppCache.php: -------------------------------------------------------------------------------- 1 | load($envFile); 16 | } 17 | 18 | $bundles = [ 19 | new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), 20 | new Symfony\Bundle\SecurityBundle\SecurityBundle(), 21 | new Symfony\Bundle\TwigBundle\TwigBundle(), 22 | new Symfony\Bundle\MonologBundle\MonologBundle(), 23 | new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(), 24 | new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(), 25 | new Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle(), 26 | new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(), 27 | new Vich\UploaderBundle\VichUploaderBundle(), 28 | new FOS\UserBundle\FOSUserBundle(), 29 | new AppBundle\AppBundle(), 30 | ]; 31 | 32 | if (in_array($this->getEnvironment(), ['dev', 'test'], true)) { 33 | $bundles[] = new Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle(); 34 | $bundles[] = new Symfony\Bundle\DebugBundle\DebugBundle(); 35 | $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle(); 36 | $bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle(); 37 | 38 | if ('dev' === $this->getEnvironment()) { 39 | $bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle(); 40 | $bundles[] = new Symfony\Bundle\WebServerBundle\WebServerBundle(); 41 | } 42 | } 43 | 44 | return $bundles; 45 | } 46 | 47 | public function getRootDir() 48 | { 49 | return __DIR__; 50 | } 51 | 52 | public function getCacheDir() 53 | { 54 | return dirname(__DIR__).'/var/cache/'.$this->getEnvironment(); 55 | } 56 | 57 | public function getLogDir() 58 | { 59 | return dirname(__DIR__).'/var/logs'; 60 | } 61 | 62 | public function registerContainerConfiguration(LoaderInterface $loader) 63 | { 64 | $loader->load($this->getRootDir().'/config/config_'.$this->getEnvironment().'.yml'); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/DoctrineMigrations/Version20170701083839.php: -------------------------------------------------------------------------------- 1 | abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 20 | 21 | $this->addSql("INSERT INTO `seed_categories` (`id`, `name`, `slug`, `description`, `updated_at`, `created_at`) VALUES 22 | (1, 'Herb', 'herb', NULL, NULL, NOW()), 23 | (2, 'Vegetable', 'vegetable', NULL, NULL, NOW()), 24 | (3, 'Sprout/Microgreens', 'sprout-microgreens', NULL, NULL, NOW()), 25 | (4, 'Fruit', 'fruit', NULL, NULL, NOW()), 26 | (5, 'Tubber', 'tubber', NULL, NULL, NOW()), 27 | (6, 'Flower', 'flower', NULL, NULL, NOW()), 28 | (7, 'Other', 'other', NULL, NULL, NOW());"); 29 | } 30 | 31 | /** 32 | * @param Schema $schema 33 | */ 34 | public function down(Schema $schema) 35 | { 36 | // this down() migration is auto-generated, please modify it to your needs 37 | $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 38 | 39 | $this->addSql('TRUNCATE TABLE `seed_categories`;'); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/DoctrineMigrations/Version20170907000538.php: -------------------------------------------------------------------------------- 1 | abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 20 | 21 | $this->addSql('ALTER TABLE plants DROP seedling_amount'); 22 | } 23 | 24 | /** 25 | * @param Schema $schema 26 | */ 27 | public function down(Schema $schema) 28 | { 29 | // this down() migration is auto-generated, please modify it to your needs 30 | $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 31 | 32 | $this->addSql('ALTER TABLE plants ADD seedling_amount INT NOT NULL'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/DoctrineMigrations/Version20170914142257.php: -------------------------------------------------------------------------------- 1 | abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 20 | 21 | $this->addSql('ALTER TABLE areas ADD field_id INT DEFAULT NULL'); 22 | $this->addSql('ALTER TABLE areas ADD CONSTRAINT FK_58B0B25C443707B0 FOREIGN KEY (field_id) REFERENCES fields (id)'); 23 | $this->addSql('CREATE INDEX IDX_58B0B25C443707B0 ON areas (field_id)'); 24 | } 25 | 26 | /** 27 | * @param Schema $schema 28 | */ 29 | public function down(Schema $schema) 30 | { 31 | // this down() migration is auto-generated, please modify it to your needs 32 | $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 33 | 34 | $this->addSql('ALTER TABLE areas DROP FOREIGN KEY FK_58B0B25C443707B0'); 35 | $this->addSql('DROP INDEX IDX_58B0B25C443707B0 ON areas'); 36 | $this->addSql('ALTER TABLE areas DROP field_id'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/DoctrineMigrations/Version20170915083636.php: -------------------------------------------------------------------------------- 1 | abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 20 | 21 | $this->addSql('ALTER TABLE tasks ADD field_id INT DEFAULT NULL'); 22 | $this->addSql('ALTER TABLE tasks ADD CONSTRAINT FK_50586597443707B0 FOREIGN KEY (field_id) REFERENCES fields (id)'); 23 | $this->addSql('CREATE INDEX IDX_50586597443707B0 ON tasks (field_id)'); 24 | } 25 | 26 | /** 27 | * @param Schema $schema 28 | */ 29 | public function down(Schema $schema) 30 | { 31 | // this down() migration is auto-generated, please modify it to your needs 32 | $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 33 | 34 | $this->addSql('ALTER TABLE tasks DROP FOREIGN KEY FK_50586597443707B0'); 35 | $this->addSql('DROP INDEX IDX_50586597443707B0 ON tasks'); 36 | $this->addSql('ALTER TABLE tasks DROP field_id'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/DoctrineMigrations/Version20170918155155.php: -------------------------------------------------------------------------------- 1 | abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 20 | 21 | $this->addSql('CREATE TABLE areasdevices (id INT AUTO_INCREMENT NOT NULL, area_id INT DEFAULT NULL, device_id INT DEFAULT NULL, updated_at DATETIME DEFAULT NULL, created_at DATETIME NOT NULL, INDEX IDX_BC0E507EBD0F409C (area_id), INDEX IDX_BC0E507E94A4C7D4 (device_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB'); 22 | $this->addSql('CREATE TABLE devices (id INT AUTO_INCREMENT NOT NULL, field_id INT DEFAULT NULL, name VARCHAR(100) NOT NULL, description LONGTEXT DEFAULT NULL, device_type INT NOT NULL, updated_at DATETIME DEFAULT NULL, created_at DATETIME NOT NULL, INDEX IDX_11074E9A443707B0 (field_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB'); 23 | $this->addSql('ALTER TABLE areasdevices ADD CONSTRAINT FK_BC0E507EBD0F409C FOREIGN KEY (area_id) REFERENCES areas (id)'); 24 | $this->addSql('ALTER TABLE areasdevices ADD CONSTRAINT FK_BC0E507E94A4C7D4 FOREIGN KEY (device_id) REFERENCES devices (id)'); 25 | $this->addSql('ALTER TABLE devices ADD CONSTRAINT FK_11074E9A443707B0 FOREIGN KEY (field_id) REFERENCES fields (id)'); 26 | } 27 | 28 | /** 29 | * @param Schema $schema 30 | */ 31 | public function down(Schema $schema) 32 | { 33 | // this down() migration is auto-generated, please modify it to your needs 34 | $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 35 | 36 | $this->addSql('ALTER TABLE areasdevices DROP FOREIGN KEY FK_BC0E507E94A4C7D4'); 37 | $this->addSql('DROP TABLE areasdevices'); 38 | $this->addSql('DROP TABLE devices'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/DoctrineMigrations/Version20170930124648.php: -------------------------------------------------------------------------------- 1 | abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 20 | 21 | $this->addSql('CREATE TABLE resources (id INT AUTO_INCREMENT NOT NULL, type VARCHAR(100) NOT NULL, data_type VARCHAR(100) NOT NULL, unit VARCHAR(100) NOT NULL, updated_at DATETIME DEFAULT NULL, created_at DATETIME NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB'); 22 | $this->addSql('CREATE TABLE resourcesdevices (id INT AUTO_INCREMENT NOT NULL, device_id INT DEFAULT NULL, resource_id INT DEFAULT NULL, name VARCHAR(100) NOT NULL, description LONGTEXT DEFAULT NULL, rid VARCHAR(100) NOT NULL, updated_at DATETIME DEFAULT NULL, created_at DATETIME NOT NULL, INDEX IDX_E27EDE6B94A4C7D4 (device_id), INDEX IDX_E27EDE6B89329D25 (resource_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB'); 23 | $this->addSql('ALTER TABLE resourcesdevices ADD CONSTRAINT FK_E27EDE6B94A4C7D4 FOREIGN KEY (device_id) REFERENCES devices (id)'); 24 | $this->addSql('ALTER TABLE resourcesdevices ADD CONSTRAINT FK_E27EDE6B89329D25 FOREIGN KEY (resource_id) REFERENCES resources (id)'); 25 | } 26 | 27 | /** 28 | * @param Schema $schema 29 | */ 30 | public function down(Schema $schema) 31 | { 32 | // this down() migration is auto-generated, please modify it to your needs 33 | $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 34 | 35 | $this->addSql('ALTER TABLE resourcesdevices DROP FOREIGN KEY FK_E27EDE6B89329D25'); 36 | $this->addSql('DROP TABLE resources'); 37 | $this->addSql('DROP TABLE resourcesdevices'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/DoctrineMigrations/Version20170930171444.php: -------------------------------------------------------------------------------- 1 | abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 20 | 21 | $this->addSql('ALTER TABLE resourcesdevices ADD data_type VARCHAR(20) NOT NULL, ADD unit VARCHAR(20) NOT NULL'); 22 | } 23 | 24 | /** 25 | * @param Schema $schema 26 | */ 27 | public function down(Schema $schema) 28 | { 29 | // this down() migration is auto-generated, please modify it to your needs 30 | $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 31 | 32 | $this->addSql('ALTER TABLE resourcesdevices DROP data_type, DROP unit'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/DoctrineMigrations/Version20171003083933.php: -------------------------------------------------------------------------------- 1 | abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 20 | 21 | $this->addSql('ALTER TABLE resources DROP data_type, DROP unit'); 22 | 23 | // seeding resources data 24 | $this->addSql('INSERT INTO resources (`type`, `created_at`) VALUES ("Temperature", NOW())'); 25 | $this->addSql('INSERT INTO resources (`type`, `created_at`) VALUES ("Humidity", NOW())'); 26 | $this->addSql('INSERT INTO resources (`type`, `created_at`) VALUES ("Light", NOW())'); 27 | $this->addSql('INSERT INTO resources (`type`, `created_at`) VALUES ("Nutrition", NOW())'); 28 | $this->addSql('INSERT INTO resources (`type`, `created_at`) VALUES ("Moisture", NOW())'); 29 | $this->addSql('INSERT INTO resources (`type`, `created_at`) VALUES ("pH", NOW())'); 30 | $this->addSql('INSERT INTO resources (`type`, `created_at`) VALUES ("On/Off State", NOW())'); 31 | $this->addSql('INSERT INTO resources (`type`, `created_at`) VALUES ("Custom", NOW())'); 32 | } 33 | 34 | /** 35 | * @param Schema $schema 36 | */ 37 | public function down(Schema $schema) 38 | { 39 | // this down() migration is auto-generated, please modify it to your needs 40 | $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 41 | 42 | $this->addSql('ALTER TABLE resources ADD data_type VARCHAR(100) NOT NULL COLLATE utf8_unicode_ci, ADD unit VARCHAR(100) NOT NULL COLLATE utf8_unicode_ci'); 43 | 44 | // emptying the table 45 | $this->addSql('TRUNCATE TABLE resources'); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/DoctrineMigrations/Version20171004065248.php: -------------------------------------------------------------------------------- 1 | abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 20 | 21 | $this->addSql('CREATE TABLE settings (id INT AUTO_INCREMENT NOT NULL, `key` VARCHAR(200) NOT NULL, value VARCHAR(200) NOT NULL, updated_at DATETIME DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB'); 22 | 23 | // add the default key and value 24 | $this->addSql('INSERT INTO settings (`key`, `value`) VALUES ("mqtt_host", "broker.mqttdashboard.com")'); 25 | $this->addSql('INSERT INTO settings (`key`, `value`) VALUES ("mqtt_port", "8000")'); 26 | } 27 | 28 | /** 29 | * @param Schema $schema 30 | */ 31 | public function down(Schema $schema) 32 | { 33 | // this down() migration is auto-generated, please modify it to your needs 34 | $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.'); 35 | 36 | $this->addSql('DROP TABLE settings'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/Resources/FOSUserBundle/views/ChangePassword/change_password.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "@FOSUser/layout.html.twig" %} 2 | 3 | {% block fos_user_content %} 4 | {% include "@FOSUser/ChangePassword/change_password_content.html.twig" %} 5 | {% endblock fos_user_content %} 6 | -------------------------------------------------------------------------------- /app/Resources/FOSUserBundle/views/ChangePassword/change_password_content.html.twig: -------------------------------------------------------------------------------- 1 | {% trans_default_domain 'FOSUserBundle' %} 2 | 3 | {{ form_start(form, { 'action': path('fos_user_change_password'), 'attr': { 'class': 'fos_user_change_password' } }) }} 4 | {{ form_widget(form) }} 5 |
6 | 7 |
8 | {{ form_end(form) }} 9 | -------------------------------------------------------------------------------- /app/Resources/FOSUserBundle/views/Profile/edit.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base.html.twig' %} 2 | 3 | {% block body %} 4 |
5 | {% include 'navbar.html.twig' %} 6 | {% include 'sidebar.html.twig' %} 7 | {% include "@FOSUser/Profile/edit_content.html.twig" %} 8 |
9 | {% endblock body %} 10 | -------------------------------------------------------------------------------- /app/Resources/FOSUserBundle/views/Profile/edit_content.html.twig: -------------------------------------------------------------------------------- 1 | {% trans_default_domain 'FOSUserBundle' %} 2 | 3 |
4 |
5 |

{% trans from "dashboard" %}User Profile{% endtrans %}

6 |
7 |
8 |
9 |
10 |
11 |
12 | {{ form_start(form, { 'action': path('fos_user_profile_edit'), 'attr': { 'class': 'fos_user_profile_edit' } }) }} 13 | {{ form_errors(form) }} 14 |
15 | {{ form_label(form.username) }} 16 | {{ form_errors(form.username) }} 17 | {{ form_widget(form.username, {'attr': {'class': 'form-control'}}) }} 18 |
19 |
20 | {{ form_label(form.email) }} 21 | {{ form_errors(form.email) }} 22 | {{ form_widget(form.email, {'attr': {'class': 'form-control'}}) }} 23 |
24 |
25 | {{ form_label(form.current_password) }} 26 | {{ form_errors(form.current_password) }} 27 | {{ form_widget(form.current_password, {'attr': {'class': 'form-control'}}) }} 28 |
29 |
30 |
31 | 32 |
33 |
34 | {{ form_end(form) }} 35 |
36 |
37 |
38 |
39 |
40 |
41 | -------------------------------------------------------------------------------- /app/Resources/FOSUserBundle/views/Profile/show.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "@FOSUser/layout.html.twig" %} 2 | 3 | {% block fos_user_content %} 4 | {% include "@FOSUser/Profile/show_content.html.twig" %} 5 | {% endblock fos_user_content %} 6 | -------------------------------------------------------------------------------- /app/Resources/FOSUserBundle/views/Profile/show_content.html.twig: -------------------------------------------------------------------------------- 1 | {% trans_default_domain 'FOSUserBundle' %} 2 | 3 |
4 |

{{ 'profile.show.username'|trans }}: {{ user.username }}

5 |

{{ 'profile.show.email'|trans }}: {{ user.email }}

6 |
7 | -------------------------------------------------------------------------------- /app/Resources/FOSUserBundle/views/Registration/check_email.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "@FOSUser/layout.html.twig" %} 2 | 3 | {% trans_default_domain 'FOSUserBundle' %} 4 | 5 | {% block fos_user_content %} 6 |

{{ 'registration.check_email'|trans({'%email%': user.email}) }}

7 | {% endblock fos_user_content %} 8 | -------------------------------------------------------------------------------- /app/Resources/FOSUserBundle/views/Registration/confirmed.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "@FOSUser/layout.html.twig" %} 2 | 3 | {% trans_default_domain 'FOSUserBundle' %} 4 | 5 | {% block fos_user_content %} 6 |

{{ 'registration.confirmed'|trans({'%username%': user.username}) }}

7 | {% if targetUrl %} 8 |

{{ 'registration.back'|trans }}

9 | {% endif %} 10 | {% endblock fos_user_content %} 11 | -------------------------------------------------------------------------------- /app/Resources/FOSUserBundle/views/Registration/email.txt.twig: -------------------------------------------------------------------------------- 1 | {% trans_default_domain 'FOSUserBundle' %} 2 | {% block subject %} 3 | {%- autoescape false -%} 4 | {{ 'registration.email.subject'|trans({'%username%': user.username, '%confirmationUrl%': confirmationUrl}) }} 5 | {%- endautoescape -%} 6 | {% endblock %} 7 | 8 | {% block body_text %} 9 | {% autoescape false %} 10 | {{ 'registration.email.message'|trans({'%username%': user.username, '%confirmationUrl%': confirmationUrl}) }} 11 | {% endautoescape %} 12 | {% endblock %} 13 | {% block body_html %}{% endblock %} 14 | -------------------------------------------------------------------------------- /app/Resources/FOSUserBundle/views/Registration/register.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "@FOSUser/layout.html.twig" %} 2 | 3 | {% block fos_user_content %} 4 | {% include "@FOSUser/Registration/register_content.html.twig" %} 5 | {% endblock fos_user_content %} 6 | -------------------------------------------------------------------------------- /app/Resources/FOSUserBundle/views/Registration/register_content.html.twig: -------------------------------------------------------------------------------- 1 | {% trans_default_domain 'FOSUserBundle' %} 2 | 3 |
4 |
5 |
6 |
7 |
8 | 9 |

{% trans from "dashboard" %}MANAGE FARMS EASIER & SMARTER{% endtrans %}

10 |

{% trans from "dashboard" %}This impressive and modern farm management application will help you to manage the operations of your farm in a more intuitive, collaborative, and efficient way.{% endtrans %}

11 |
12 |
13 | {{ form_start(form, {'method': 'post', 'action': path('fos_user_registration_register'), 'attr': {'class': 'fos_user_registration_register'}}) }} 14 | {% trans from "dashboard" %}Register New User{% endtrans %} 15 |
16 | {{ form_label(form.email, 'Email') }} 17 | {{ form_widget(form.email, {'attr': {'class': 'form-control'}}) }} 18 |
19 |
20 | {{ form_label(form.username, 'Username') }} 21 | {{ form_widget(form.username, {'attr': {'class': 'form-control'}}) }} 22 |
23 |
24 | {{ form_widget(form.plainPassword) }} 25 |
26 |
27 | 28 |
29 | {{ form_end(form) }} 30 |
31 |
32 |
33 | 34 |
35 |
36 |
37 |
38 | -------------------------------------------------------------------------------- /app/Resources/FOSUserBundle/views/Resetting/check_email.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "@FOSUser/layout.html.twig" %} 2 | 3 | {% trans_default_domain 'FOSUserBundle' %} 4 | 5 | {% block fos_user_content %} 6 |
7 |
8 |
9 |
10 |
11 | 12 |

{% trans from "dashboard" %}MANAGE FARMS EASIER & SMARTER{% endtrans %}

13 |

{% trans from "dashboard" %}This impressive and modern farm management application will help you to manage the operations of your farm in a more intuitive, collaborative, and efficient way.{% endtrans %}

14 |
15 |
16 |

17 | {{ 'resetting.check_email'|trans({'%tokenLifetime%': tokenLifetime})|nl2br }} 18 |

19 |
20 |
21 |
22 | 23 |
24 |
25 |
26 |
27 | {% endblock %} 28 | -------------------------------------------------------------------------------- /app/Resources/FOSUserBundle/views/Resetting/email.txt.twig: -------------------------------------------------------------------------------- 1 | {% trans_default_domain 'FOSUserBundle' %} 2 | {% block subject %} 3 | {%- autoescape false -%} 4 | {{ 'resetting.email.subject'|trans({'%username%': user.username}) }} 5 | {%- endautoescape -%} 6 | {% endblock %} 7 | 8 | {% block body_text %} 9 | {% autoescape false %} 10 | {{ 'resetting.email.message'|trans({'%username%': user.username, '%confirmationUrl%': confirmationUrl}) }} 11 | {% endautoescape %} 12 | {% endblock %} 13 | {% block body_html %}{% endblock %} 14 | -------------------------------------------------------------------------------- /app/Resources/FOSUserBundle/views/Resetting/request.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "@FOSUser/layout.html.twig" %} 2 | 3 | {% block fos_user_content %} 4 | {% include "@FOSUser/Resetting/request_content.html.twig" %} 5 | {% endblock fos_user_content %} 6 | -------------------------------------------------------------------------------- /app/Resources/FOSUserBundle/views/Resetting/request_content.html.twig: -------------------------------------------------------------------------------- 1 | {% trans_default_domain 'FOSUserBundle' %} 2 | 3 |
4 |
5 |
6 |
7 |
8 | 9 |

{% trans from "dashboard" %}MANAGE FARMS EASIER & SMARTER{% endtrans %}

10 |

{% trans from "dashboard" %}This impressive and modern farm management application will help you to manage the operations of your farm in a more intuitive, collaborative, and efficient way.{% endtrans %}

11 |
12 |
13 |
14 | {% trans from "dashboard" %}Reset Password{% endtrans %} 15 |
16 | 17 | 18 |
19 |
20 | 21 |
22 |
23 |
24 |
25 |
26 | 27 |
28 |
29 |
30 |
31 | -------------------------------------------------------------------------------- /app/Resources/FOSUserBundle/views/Resetting/reset.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "@FOSUser/layout.html.twig" %} 2 | 3 | {% block fos_user_content %} 4 | {% include "@FOSUser/Resetting/reset_content.html.twig" %} 5 | {% endblock fos_user_content %} 6 | -------------------------------------------------------------------------------- /app/Resources/FOSUserBundle/views/Resetting/reset_content.html.twig: -------------------------------------------------------------------------------- 1 | {% trans_default_domain 'FOSUserBundle' %} 2 | 3 | {{ form_start(form, { 'action': path('fos_user_resetting_reset', {'token': token}), 'attr': { 'class': 'fos_user_resetting_reset' } }) }} 4 | {{ form_widget(form) }} 5 |
6 | 7 |
8 | {{ form_end(form) }} 9 | -------------------------------------------------------------------------------- /app/Resources/FOSUserBundle/views/Security/login.html.twig: -------------------------------------------------------------------------------- 1 | {% extends "@FOSUser/layout.html.twig" %} 2 | 3 | {% block fos_user_content %} 4 | {{ include('@FOSUser/Security/login_content.html.twig') }} 5 | {% endblock fos_user_content %} 6 | -------------------------------------------------------------------------------- /app/Resources/FOSUserBundle/views/Security/login_content.html.twig: -------------------------------------------------------------------------------- 1 | {% trans_default_domain 'FOSUserBundle' %} 2 | 3 |
4 |
5 |
6 |
7 |
8 | 9 |

{% trans from "dashboard" %}MANAGE FARMS EASIER & SMARTER{% endtrans %}

10 |

{% trans from "dashboard" %}This impressive and modern farm management application will help you to manage the operations of your farm in a more intuitive, collaborative, and efficient way.{% endtrans %}

11 |
12 |
13 |
14 | {% trans from "dashboard" %}Sign In to start working.{% endtrans %} 15 | {% if error %} 16 | 17 | {% endif %} 18 | {% if csrf_token %} 19 | 20 | {% endif %} 21 |
22 | 23 | 24 |
25 |
26 | 27 | 28 |
29 |
30 | 31 | 32 |
33 |
34 | 35 |
36 | 39 |
40 |

{% trans from "dashboard" %}Have no account?{% endtrans %} {% trans from "dashboard" %}Sign Up{% endtrans %} {% trans from "dashboard" %}here.{% endtrans %}

41 |
42 |
43 |
44 |
45 |
46 | 47 |
48 |
49 |
50 |
-------------------------------------------------------------------------------- /app/Resources/FOSUserBundle/views/layout.html.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | {% block title %}TANIA{% endblock %} 12 | 13 | {% block stylesheets %} 14 | 15 | 16 | 17 | {% endblock %} 18 | 19 | 23 | 24 | 25 | {% block fos_user_content %}{% endblock fos_user_content %} 26 | 27 | {% block javascripts %}{% endblock %} 28 | 29 | -------------------------------------------------------------------------------- /app/Resources/views/area/index.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base.html.twig' %} 2 | 3 | {% block body %} 4 | {% trans_default_domain "dashboard" %} 5 |
6 | {% include 'navbar.html.twig' %} 7 | {% include 'sidebar.html.twig' %} 8 | 9 |
10 |
11 | {% trans %}Add Area{% endtrans %} 12 |

{% trans %}All Areas{% endtrans %}

13 |
14 |
15 |
16 | {% set index = 0 %} 17 | {% for area in areas %} 18 |
19 |
20 | {% if vich_uploader_asset(area, 'imageFile') %} 21 |
22 | {% endif %} 23 |
24 |
25 | 26 | {% if area.reservoir is not null %} 27 |
{{ area.reservoir.field.name }}
28 | {% endif %} 29 |
30 |
31 |
32 |
{% trans %}System{% endtrans %}
33 |
34 | {{ growingMethods[index] }} 35 |
36 |
37 |
38 |
{% trans %}Capacity{% endtrans %}
39 |
40 | {{ area.capacity }} {{ measurementUnits[index] }} 41 |
42 |
43 |
44 |
45 |
46 |
47 | {% set index = index + 1 %} 48 | {% endfor %} 49 |
50 |
51 |
52 | {% include 'right-sidebar.html.twig' %} 53 |
54 | {% endblock %} -------------------------------------------------------------------------------- /app/Resources/views/base.html.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | {% block title %}Tania{% endblock %} 12 | 13 | {% block stylesheets %} 14 | 15 | 16 | 17 | 18 | 19 | 20 | {% endblock %} 21 | 22 | 26 | 27 | 28 | 29 | 30 | {% block body %}{% endblock %} 31 | 32 | {% block javascripts %} 33 | 34 | 35 | 36 | 37 | 38 | {% if classActive == "fields_create" %} 39 | 40 | 41 | {% elseif classActive == "fields_show" %} 42 | 43 | 44 | {% elseif classActive == "areas_create" or classActive == "areas_edit" %} 45 | 46 | {% endif %} 47 | 48 | 53 | {% endblock %} 54 | 55 | 56 | -------------------------------------------------------------------------------- /app/Resources/views/device/areas.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base.html.twig' %} 2 | 3 | {% block body %} 4 | {% trans_default_domain "dashboard" %} 5 |
6 | {% include 'navbar.html.twig' %} 7 | {% include 'sidebar.html.twig' %} 8 |
9 |
10 |

{% trans %}Areas for{% endtrans %} {{ device.name }}

11 |
12 |
13 |
14 |
15 |
16 |
17 | {{ form_start(form, {'attr': {'class': 'group-border-dashed', 'style': 'border-radius: 0px;'}}) }} 18 | {{ form_errors(form) }} 19 |
20 | {{ form_label(form.area, 'Area', {'label_attr': {'class': 'control-label'}}) }} 21 | {{ form_errors(form.area) }} 22 | {{ form_widget(form.area, {'attr': {'class': 'form-control'}}) }} 23 |
24 |
25 |
26 | {{ form_widget(form.save, {'attr': {'class': 'btn btn-primary btn-lg'}}) }} 27 | {% trans %}Cancel{% endtrans %} 28 |
29 |
30 | {{form_end(form)}} 31 |
32 |
33 |
34 |
35 |
36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | {% for areaDevice in areasDevices %} 46 | 47 | 48 | 55 | 56 | {% endfor %} 57 | 58 |
Area NameActions
{{ areaDevice.area.name }} 49 |
50 | 51 | 52 | 53 |
54 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | {% include 'right-sidebar.html.twig' %} 66 |
67 | {% endblock %} -------------------------------------------------------------------------------- /app/Resources/views/device/create.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base.html.twig' %} 2 | 3 | {% block body %} 4 | {% trans_default_domain "dashboard" %} 5 |
6 | {% include 'navbar.html.twig' %} 7 | {% include 'sidebar.html.twig' %} 8 | 9 |
10 |
11 |

{% trans %}Add New Device{% endtrans %}

12 |
13 |
14 |
15 |
16 |
17 |
18 | {{ form_start(form, {'attr': {'class': 'form-horizontal group-border-dashed', 'style': 'border-radius: 0px;'}}) }} 19 | {{ form_errors(form) }} 20 |
21 | {{ form_label(form.name, 'Name', {'label_attr': {'class': 'col-sm-3 control-label'}}) }} 22 |
23 | {{ form_errors(form.name) }} 24 | {{ form_widget(form.name, {'attr': {'class': 'form-control', 'placeholder': 'e.g. VEG EC01, etc'}}) }} 25 |
26 |
27 |
28 | {{ form_label(form.description, 'Description', {'label_attr': {'class': 'col-sm-3 control-label'}}) }} 29 |
30 | {{ form_errors(form.description) }} 31 | {{ form_widget(form.description, {'attr': {'class': 'form-control'}}) }} 32 |
33 |
34 |
35 | {{ form_label(form.deviceType, 'Device Type', {'label_attr': {'class': 'col-sm-3 control-label'}}) }} 36 |
37 | {{ form_errors(form.deviceType) }} 38 | {{ form_widget(form.deviceType, {'attr': {'class': 'form-control'}}) }} 39 |
40 |
41 |
42 |
43 | {{ form_widget(form.save, {'attr': {'class': 'btn btn-primary btn-lg'}}) }} 44 | {% trans %}Cancel{% endtrans %} 45 |
46 |
47 | {{form_end(form)}} 48 |
49 |
50 |
51 |
52 |
53 |
54 | 55 | {% include 'right-sidebar.html.twig' %} 56 |
57 | {% endblock %} -------------------------------------------------------------------------------- /app/Resources/views/device/index.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base.html.twig' %} 2 | 3 | {% block body %} 4 | {% trans_default_domain "dashboard" %} 5 |
6 | {% include 'navbar.html.twig' %} 7 | {% include 'sidebar.html.twig' %} 8 | 9 |
10 |
11 | {% trans %}Add New Device{% endtrans %} 12 |

{% trans %}All Devices{% endtrans %}

13 |
14 |
15 |
16 |
17 |
18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | {% for device in devices %} 33 | 34 | 35 | 36 | 37 | 38 | 39 | 42 | 48 | 49 | {% endfor %} 50 | 51 |
{% trans %}Name{% endtrans %}{% trans %}Resources{% endtrans %}{% trans %}Register Date{% endtrans %}{% trans %}Located On{% endtrans %}{% trans %}Last Connected{% endtrans %}{% trans %}Actions{% endtrans %}{% trans %}Delete?{% endtrans %}
{{ device.name }}{{ device.resourcesdevices|length }} {% trans %}resources{% endtrans %}{{ device.createdAt|date('d-m-Y') }}{{ device.areasdevices|length }} {% trans %}areas{% endtrans %}None 40 | {% trans %}Info{% endtrans %} | {% trans %}Add Resources{% endtrans %} | {% trans %}Add Areas{% endtrans %} 41 | 43 |
44 | 45 | 46 |
47 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | 59 | {% include 'right-sidebar.html.twig' %} 60 |
61 | {% endblock %} -------------------------------------------------------------------------------- /app/Resources/views/device/show.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base.html.twig' %} 2 | 3 | {% block body %} 4 | {% trans_default_domain "dashboard" %} 5 |
6 | {% include 'navbar.html.twig' %} 7 | {% include 'sidebar.html.twig' %} 8 |
9 |
10 |

{% trans %}Detail Information for{% endtrans %} {{ device.name }}

11 |
12 |
13 |
14 |
15 |

Device Type: {{ device.deviceType }}

16 |

Description: {{ device.description }}

17 |
18 |
19 |
20 |
21 |

Resources:

22 |
23 | {% for resourceDevice in resourcesDevices %} 24 |

25 | Name: {{ resourceDevice.name }}
26 | Description: {{ resourceDevice.description }}
27 | MQTT Channel (RID): tania/{{ resourceDevice.rid }}
28 | Data Type: {{ resourceDevice.dataType }}
29 | Unit: {{ resourceDevice.unit }} 30 |

31 | {% endfor %} 32 |
33 |
34 |
35 |

Areas:

36 |
37 |
    38 | {% for areaDevice in areasDevices %} 39 |
  • 40 | {{ areaDevice.area.name }} 41 |
  • 42 | {% endfor %} 43 |
44 |
45 |
46 |
47 |
48 |
49 | {% include 'right-sidebar.html.twig' %} 50 |
51 | {% endblock %} -------------------------------------------------------------------------------- /app/Resources/views/field/add.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base.html.twig' %} 2 | 3 | {% block body %} 4 | {% trans_default_domain "dashboard" %} 5 |
6 | {% include 'navbar.html.twig' %} 7 | {% include 'sidebar.html.twig' %} 8 | 9 |
10 |
11 |

{% trans %}Add New Farm{% endtrans %}

12 |
13 |
14 |
15 |
16 |
17 |
18 | {{ form_start(form) }} 19 | {{ form_errors(form) }} 20 |
21 | {{ form_label(form.name, 'Name (0/50 chars)', {'label_attr': {'id': 'label_field_name'}}) }} 22 | {{ form_errors(form.name) }} 23 | {{ form_widget(form.name, {'attr': {'class': 'form-control'}}) }} 24 |
25 |
26 |
27 |
28 | {{ form_label(form.lat, 'Latitude') }} 29 | {{ form_errors(form.lat) }} 30 | {{ form_widget(form.lat, {'attr': {'class': 'form-control'}}) }} 31 |
32 |
33 | {{ form_label(form.lng, 'Longitude') }} 34 | {{ form_errors(form.lng) }} 35 | {{ form_widget(form.lng, {'attr': {'class': 'form-control'}}) }} 36 |
37 |
38 |
39 |
40 | {{ form_label(form.description) }} 41 | {{ form_errors(form.description) }} 42 | {{ form_widget(form.description, {'attr': {'class': 'form-control'}}) }} 43 |
44 |
45 | {{ form_label(form.imageFile) }} 46 | {{ form_errors(form.imageFile) }} 47 | {{ form_widget(form.imageFile, {'attr': {'class': 'form-control'}}) }} 48 |
49 |
50 |
51 | {{ form_widget(form.save, {'attr': {'class': 'btn btn-primary btn-lg'}}) }} 52 | {% trans %}Cancel{% endtrans %} 53 |
54 |
55 | {{form_end(form)}} 56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | {% include 'right-sidebar.html.twig' %} 66 |
67 | 68 | {% endblock %} -------------------------------------------------------------------------------- /app/Resources/views/field/index.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base.html.twig' %} 2 | 3 | {% block body %} 4 | {% trans_default_domain "dashboard" %} 5 |
6 | {% include 'navbar.html.twig' %} 7 | {% include 'sidebar.html.twig' %} 8 | 9 |
10 |
11 | 12 | {% trans %}Add New Farm{% endtrans %} 13 | 14 |

{% trans %}All Farms/Greenhouses{% endtrans %}

15 |
16 |
17 |
18 | {% for field in fields %} 19 |
20 |
21 | {% if vich_uploader_asset(field, 'imageFile') %} 22 |
23 | {% endif %} 24 |
25 |
26 | 27 |
28 |
29 |
30 |
31 | {% endfor %} 32 |
33 |
34 |
35 | {% include 'right-sidebar.html.twig' %} 36 |
37 | {% endblock %} -------------------------------------------------------------------------------- /app/Resources/views/navbar.html.twig: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/Resources/views/plant/harvest.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base.html.twig' %} 2 | 3 | {% block body %} 4 | {% trans_default_domain "dashboard" %} 5 |
6 | {% include 'navbar.html.twig' %} 7 | {% include 'sidebar.html.twig' %} 8 | 9 |
10 |
11 |

{% trans %}Action for{% endtrans %} {{ plant.seed.name }}

12 |
13 | 14 |
15 |
16 |
17 |
18 |
19 | {% for message in app.flashes('notice') %} 20 |
21 | {{ message }} 22 |
23 | {% endfor %} 24 | {{ form_start(form) }} 25 |
26 | 27 | 28 |
29 |
30 | {{ form_label(form.action, 'Harvest or Dispose') }} 31 | {{ form_widget(form.action) }} 32 |
33 |
34 | {{ form_label(form.note) }} 35 | {{ form_errors(form.note) }} 36 | {{ form_widget(form.note, {'attr': {'class': 'form-control'}}) }} 37 |
38 |
39 |
40 | {{ form_widget(form.save, {'attr': {'class': 'btn btn-primary btn-lg'}}) }} 41 | {% trans %}Cancel{% endtrans %} 42 |
43 |
44 | {{ form_end(form) }} 45 |
46 |
47 |
48 |
49 |
50 |
51 | {% include 'right-sidebar.html.twig' %} 52 |
53 | {% endblock %} -------------------------------------------------------------------------------- /app/Resources/views/plant/index.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base.html.twig' %} 2 | 3 | {% block body %} 4 | {% trans_default_domain "dashboard" %} 5 |
6 | {% include 'navbar.html.twig' %} 7 | {% include 'sidebar.html.twig' %} 8 | 9 |
10 |
11 | {% trans %}Add plant{% endtrans %} 12 |

{% trans %}Plant Varieties{% endtrans %}

13 |
14 | 15 |
16 |
17 | {% for plant in plants %} 18 |
19 |
20 | {% if vich_uploader_asset(plant['seed'], 'imageFile', 'AppBundle\\Entity\\Seed') %} 21 |
22 | {% endif %} 23 |
24 |
25 | 26 |
{{ plant['seed_category'] }}
27 |
28 |
29 |
30 |
{% trans %}Amount{% endtrans %}
31 |
{{ plant['seedling_total'] }}
32 |
33 |
34 |
{% trans %}Total Seedling Area{% endtrans %}
35 |
{{ plant['area_count'] }}
36 |
37 |
38 |
39 |
40 |
41 | {% endfor %} 42 |
43 |
44 |
45 | {% include 'right-sidebar.html.twig' %} 46 |
47 | {% endblock %} -------------------------------------------------------------------------------- /app/Resources/views/plant/show.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base.html.twig' %} 2 | 3 | {% block body %} 4 | {% trans_default_domain "dashboard" %} 5 |
6 | {% include 'navbar.html.twig' %} 7 | {% include 'sidebar.html.twig' %} 8 | 9 |
10 |
11 | 14 |

{{ plants[0].seed.name }}

15 |
16 | 17 |
18 | 61 |
62 |
63 | {% include 'right-sidebar.html.twig' %} 64 |
65 | {% endblock %} -------------------------------------------------------------------------------- /app/Resources/views/reservoir/show.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base.html.twig' %} 2 | 3 | {% block body %} 4 | {% trans_default_domain "dashboard" %} 5 |
6 | {% include 'navbar.html.twig' %} 7 | {% include 'sidebar.html.twig' %} 8 | 9 |
10 |
11 |

{% trans %}Edit Reservoir{% endtrans %}: {{ reservoir.name }}

12 |
13 | 14 |
15 |
16 |
17 |
18 |
19 | {{ form_start(form) }} 20 | {{ form_errors(form) }} 21 |
22 |
23 |
24 | {{ form_label(form.name) }} 25 | {{ form_errors(form.name) }} 26 | {{ form_widget(form.name, {'attr': {'class': 'form-control'}}) }} 27 |
28 |
29 | {{ form_label(form.field) }} 30 | {{ form_errors(form.field) }} 31 | {{ form_widget(form.field, {'attr': {'class': 'form-control'}}) }} 32 |
33 |
34 |
35 |
36 |
37 |
38 | {{ form_label(form.capacity) }} 39 | {{ form_errors(form.capacity) }} 40 | {{ form_widget(form.capacity, {'attr': {'class': 'form-control'}}) }} 41 |
42 |
43 | {{ form_label(form.measurementUnit) }} 44 | {{ form_errors(form.measurementUnit) }} 45 | {{ form_widget(form.measurementUnit, {'attr': {'class': 'form-control'}}) }} 46 |
47 |
48 |
49 |
50 |
51 | {{ form_widget(form.save, {'attr': {'class': 'btn btn-primary btn-lg'}}) }} 52 | {% trans %}Cancel{% endtrans %} 53 |
54 |
55 | {{ form_end(form) }} 56 |
57 |
58 |
59 |
60 |
61 |
62 | {% include 'right-sidebar.html.twig' %} 63 |
64 | {% endblock %} -------------------------------------------------------------------------------- /app/Resources/views/right-sidebar.html.twig: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/Resources/views/settings/index.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base.html.twig' %} 2 | 3 | {% block body %} 4 | {% trans_default_domain "dashboard" %} 5 |
6 | {% include 'navbar.html.twig' %} 7 | {% include 'sidebar.html.twig' %} 8 | 9 |
10 |
11 |

Tania {% trans %}Preferences{% endtrans %}

12 |
13 |
14 | 15 | 16 |
17 |
18 |
19 |
20 | {% trans %}Internet of Things{% endtrans %} 21 |
22 |
23 | {{ form_start(form, {'attr': {'class': 'form-horizontal group-border-dashed'}}) }} 24 | {{ form_errors(form) }} 25 |
26 | {{ form_label(form.mqttHost, 'MQTT Host', { 'label_attr': {'class': 'col-sm-3 control-label'}}) }} 27 |
28 | {{ form_errors(form.mqttHost) }} 29 | {{ form_widget(form.mqttHost, {'attr': {'class': 'form-control'}}) }} 30 |
31 |
32 |
33 | {{ form_label(form.mqttPort, 'MQTT Port', { 'label_attr': {'class': 'col-sm-3 control-label'}}) }} 34 |
35 | {{ form_errors(form.mqttPort) }} 36 | {{ form_widget(form.mqttPort, {'attr': {'class': 'form-control'}}) }} 37 |
38 |
39 |
40 |
41 | {{ form_widget(form.save, {'attr': {'class': 'btn btn-primary btn-lg'}}) }} 42 |
43 |
44 | {{ form_end(form) }} 45 |
46 |
47 |
48 |
49 |
50 |
51 | {% include 'right-sidebar.html.twig' %} 52 |
53 | {% endblock %} -------------------------------------------------------------------------------- /app/Resources/views/task/index.html.twig: -------------------------------------------------------------------------------- 1 | {% extends 'base.html.twig' %} 2 | 3 | {% block body %} 4 | {% trans_default_domain "dashboard" %} 5 |
6 | {% include 'navbar.html.twig' %} 7 | {% include 'sidebar.html.twig' %} 8 | 9 |
10 |
11 | {% trans %}Add New{% endtrans %} 12 |

{% trans %}Farm Tasks{% endtrans %}

13 |
14 |
15 | 16 |
17 |
18 |
19 |
{% trans %}All Tasks{% endtrans %}
20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | {% for task in tasks %} 34 | 35 | 36 | 37 | 38 | 39 | 42 | 43 | 44 | {% endfor %} 45 | 46 |
{% trans %}Category{% endtrans %}{% trans %}Task{% endtrans %}{% trans %}Notes{% endtrans %}{% trans %}Due Date{% endtrans %}{% trans %}Level of Importance{% endtrans %}{% trans %}Is it done?{% endtrans %}
{{ task.category }}{{ task.name }}{{ task.notes }}{{ task.dueDate|date('d F Y h:i')}} 40 | {{ task.urgencyLevel }} 41 | {% if task.isDone == 0 %} {% trans %}No{% endtrans %} {% elseif task.isDone == 1 %} {% trans %}Yes{% endtrans %} {% endif %}
47 |
48 |
49 |
50 |
51 |
52 |
53 | {% include 'right-sidebar.html.twig' %} 54 |
55 | {% endblock %} 56 | -------------------------------------------------------------------------------- /app/config/config_dev.yml: -------------------------------------------------------------------------------- 1 | imports: 2 | - { resource: config.yml } 3 | 4 | framework: 5 | router: 6 | resource: '%kernel.project_dir%/app/config/routing_dev.yml' 7 | strict_requirements: true 8 | profiler: { only_exceptions: false } 9 | 10 | web_profiler: 11 | toolbar: true 12 | intercept_redirects: false 13 | 14 | monolog: 15 | handlers: 16 | main: 17 | type: stream 18 | path: '/tmp/stdout' 19 | level: debug 20 | channels: ['!event'] 21 | console: 22 | type: console 23 | process_psr_3_messages: false 24 | channels: ['!event', '!doctrine', '!console'] 25 | # To follow logs in real time, execute the following command: 26 | # `bin/console server:log -vv` 27 | server_log: 28 | type: server_log 29 | process_psr_3_messages: false 30 | host: 127.0.0.1:9911 31 | # uncomment to get logging in your browser 32 | # you may have to allow bigger header sizes in your Web server configuration 33 | #firephp: 34 | # type: firephp 35 | # level: info 36 | #chromephp: 37 | # type: chromephp 38 | # level: info 39 | 40 | #swiftmailer: 41 | # delivery_addresses: ['me@example.com'] 42 | -------------------------------------------------------------------------------- /app/config/config_prod.yml: -------------------------------------------------------------------------------- 1 | imports: 2 | - { resource: config.yml } 3 | 4 | #doctrine: 5 | # orm: 6 | # metadata_cache_driver: apc 7 | # result_cache_driver: apc 8 | # query_cache_driver: apc 9 | 10 | monolog: 11 | handlers: 12 | main: 13 | type: fingers_crossed 14 | action_level: error 15 | handler: nested 16 | nested: 17 | type: stream 18 | path: '/tmp/stdout' 19 | level: debug 20 | console: 21 | type: console 22 | process_psr_3_messages: false 23 | -------------------------------------------------------------------------------- /app/config/config_test.yml: -------------------------------------------------------------------------------- 1 | imports: 2 | - { resource: config_dev.yml } 3 | 4 | doctrine: 5 | dbal: 6 | host: '%env(SYMFONY_DB_HOST)%' 7 | port: '%env(SYMFONY_DB_PORT)%' 8 | dbname: '%env(SYMFONY_DB_NAME)%' 9 | user: '%env(SYMFONY_DB_USERNAME)%' 10 | password: '%env(SYMFONY_DB_PASSWORD)%' 11 | 12 | framework: 13 | test: ~ 14 | session: 15 | storage_id: session.storage.mock_file 16 | profiler: 17 | collect: false 18 | 19 | security: 20 | firewalls: 21 | main: 22 | http_basic: ~ 23 | 24 | web_profiler: 25 | toolbar: false 26 | intercept_redirects: false 27 | 28 | swiftmailer: 29 | disable_delivery: true 30 | -------------------------------------------------------------------------------- /app/config/repository.yml: -------------------------------------------------------------------------------- 1 | services: 2 | app.repository.plant_repository: 3 | class: 'AppBundle\Repository\PlantRepository' 4 | arguments: 5 | - '@doctrine.orm.entity_manager' 6 | - 'AppBundle\Entity\Plant' 7 | 8 | app.repository.task_repository: 9 | class: 'AppBundle\Repository\TaskRepository' 10 | arguments: 11 | - '@doctrine.orm.entity_manager' 12 | - 'AppBundle\Entity\Task' -------------------------------------------------------------------------------- /app/config/routing_dev.yml: -------------------------------------------------------------------------------- 1 | _wdt: 2 | resource: '@WebProfilerBundle/Resources/config/routing/wdt.xml' 3 | prefix: /_wdt 4 | 5 | _profiler: 6 | resource: '@WebProfilerBundle/Resources/config/routing/profiler.xml' 7 | prefix: /_profiler 8 | 9 | _errors: 10 | resource: '@TwigBundle/Resources/config/routing/errors.xml' 11 | prefix: /_error 12 | 13 | _main: 14 | resource: routing.yml 15 | -------------------------------------------------------------------------------- /app/config/security.yml: -------------------------------------------------------------------------------- 1 | # To get started with security, check out the documentation: 2 | # http://symfony.com/doc/current/security.html 3 | security: 4 | encoders: 5 | FOS\UserBundle\Model\UserInterface: bcrypt 6 | 7 | role_hierarchy: 8 | ROLE_ADMIN: ROLE_USER 9 | ROLE_SUPER_ADMIN: ROLE_ADMIN 10 | 11 | # http://symfony.com/doc/current/security.html#b-configuring-how-users-are-loaded 12 | providers: 13 | fos_userbundle: 14 | id: fos_user.user_provider.username 15 | 16 | firewalls: 17 | # disables authentication for assets and the profiler, adapt it according to your needs 18 | dev: 19 | pattern: ^/(_(profiler|wdt)|css|images|js)/ 20 | security: false 21 | 22 | main: 23 | # activate different ways to authenticate 24 | 25 | # http://symfony.com/doc/current/security.html#a-configuring-how-your-users-will-authenticate 26 | #http_basic: ~ 27 | 28 | # http://symfony.com/doc/current/cookbook/security/form_login_setup.html 29 | #form_login: ~ 30 | pattern: ^/ 31 | form_login: 32 | provider: fos_userbundle 33 | csrf_token_generator: security.csrf.token_manager 34 | # if you are using Symfony < 2.8, use the following config instead: 35 | # csrf_provider: form.csrf_provider 36 | 37 | logout: true 38 | anonymous: true 39 | 40 | access_control: 41 | - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY } 42 | - { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY } 43 | - { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY } 44 | - { path: ^/admin/, role: ROLE_ADMIN } 45 | - { path: ^/, role: ROLE_USER } 46 | -------------------------------------------------------------------------------- /app/config/services.yml: -------------------------------------------------------------------------------- 1 | # Learn more about services, parameters and containers at 2 | # http://symfony.com/doc/current/service_container.html 3 | parameters: 4 | #parameter_name: value 5 | 6 | services: 7 | # default configuration for services in *this* file 8 | _defaults: 9 | # automatically injects dependencies in your services 10 | autowire: true 11 | # automatically registers your services as commands, event subscribers, etc. 12 | autoconfigure: true 13 | # this means you cannot fetch services directly from the container via $container->get() 14 | # if you need to do this, you can override this setting on individual services 15 | public: false 16 | 17 | # makes classes in src/AppBundle available to be used as services 18 | # this creates a service per class whose id is the fully-qualified class name 19 | AppBundle\: 20 | resource: '../../src/AppBundle/*' 21 | # you can exclude directories or files 22 | # but if a service is unused, it's removed anyway 23 | exclude: '../../src/AppBundle/{Entity,Repository}' 24 | 25 | # controllers are imported separately to make sure they're public 26 | # and have a tag that allows actions to type-hint services 27 | AppBundle\Controller\: 28 | resource: '../../src/AppBundle/Controller' 29 | public: true 30 | tags: ['controller.service_arguments'] 31 | 32 | # add more services, or override services that need manual wiring 33 | # AppBundle\Service\ExampleService: 34 | # arguments: 35 | # $someArgument: 'some_value' 36 | 37 | app.form.registration: 38 | class: AppBundle\Form\RegistrationFormType 39 | tags: 40 | - { name: form.type, alias: app_user_registration } -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | getParameterOption(['--env', '-e'], getenv('SYMFONY_ENV') ?: 'dev'); 20 | $debug = getenv('SYMFONY_DEBUG') !== '0' && !$input->hasParameterOption(['--no-debug', '']) && $env !== 'prod'; 21 | 22 | if ($debug) { 23 | Debug::enable(); 24 | } 25 | 26 | $kernel = new AppKernel($env, $debug); 27 | $application = new Application($kernel); 28 | $application->run($input); 29 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tania", 3 | "homepage": "https://github.com/Tanibox/tania", 4 | "description": "", 5 | "main": "", 6 | "license": "Apache License 2.0 (Apache-2.0)", 7 | "ignore": [ 8 | "**/.*", 9 | "node_modules", 10 | "bower_components", 11 | "test", 12 | "tests" 13 | ], 14 | "dependencies": { 15 | "datetimepicker": "^2.5.4" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tanibox/tania", 3 | "description": "Free and open source farming management system.", 4 | "license": "Apache-2.0", 5 | "type": "project", 6 | "autoload": { 7 | "psr-4": { 8 | "AppBundle\\": "src/AppBundle" 9 | }, 10 | "classmap": [ 11 | "app/AppKernel.php", 12 | "app/AppCache.php" 13 | ] 14 | }, 15 | "autoload-dev": { 16 | "psr-4": { 17 | "Tests\\": "tests/" 18 | }, 19 | "files": [ 20 | "vendor/symfony/symfony/src/Symfony/Component/VarDumper/Resources/functions/dump.php" 21 | ] 22 | }, 23 | "require": { 24 | "php": ">=7.0", 25 | "doctrine/doctrine-bundle": "^1.6", 26 | "doctrine/doctrine-migrations-bundle": "^1.2", 27 | "doctrine/orm": "^2.5", 28 | "friendsofsymfony/user-bundle": "~2.0", 29 | "incenteev/composer-parameter-handler": "^2.0", 30 | "sensio/distribution-bundle": "^5.0.19", 31 | "sensio/framework-extra-bundle": "^3.0.2", 32 | "symfony/monolog-bundle": "^3.1.0", 33 | "symfony/options-resolver": "^3.3", 34 | "symfony/polyfill-apcu": "^1.0", 35 | "symfony/swiftmailer-bundle": "^2.3.10", 36 | "symfony/symfony": "3.3.*", 37 | "symfony/translation": "^3.3", 38 | "symfony/var-dumper": "^3.3", 39 | "twig/twig": "^1.0||^2.0", 40 | "vich/uploader-bundle": "^1.4" 41 | }, 42 | "require-dev": { 43 | "doctrine/doctrine-fixtures-bundle": "^2.3", 44 | "phpunit/phpunit": "6.2", 45 | "sensio/generator-bundle": "^3.0", 46 | "symfony/phpunit-bridge": "^3.0" 47 | }, 48 | "scripts": { 49 | "symfony-scripts": [ 50 | "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap", 51 | "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache", 52 | "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets", 53 | "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile", 54 | "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::prepareDeploymentTarget" 55 | ], 56 | "post-install-cmd": [ 57 | "@symfony-scripts" 58 | ], 59 | "post-update-cmd": [ 60 | "@symfony-scripts" 61 | ] 62 | }, 63 | "config": { 64 | "sort-packages": true 65 | }, 66 | "extra": { 67 | "symfony-app-dir": "app", 68 | "symfony-bin-dir": "bin", 69 | "symfony-var-dir": "var", 70 | "symfony-web-dir": "web", 71 | "symfony-tests-dir": "tests", 72 | "symfony-assets-install": "relative" 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /docker-compose.dev.yml: -------------------------------------------------------------------------------- 1 | 2 | version: '2.2' 3 | 4 | services: 5 | 6 | app: 7 | image: tanibox/tania:latest 8 | build: 9 | dockerfile: docker/app/Dockerfile 10 | context: . 11 | environment: 12 | SYMFONY_LOCALE: en 13 | SYMFONY_SECRET: AugIVKlefKLzqJwlwY5S5YaW8Ui66fi8 14 | SYMFONY_ENV: dev 15 | SYMFONY_DB_HOST: db 16 | SYMFONY_DB_PORT: 3306 17 | SYMFONY_DB_NAME: tania 18 | SYMFONY_DB_USERNAME: tania 19 | SYMFONY_DB_PASSWORD: taniapass 20 | SYMFONY_MAILER_TRANSPORT: smtp 21 | SYMFONY_MAILER_HOST: 127.0.0.1 22 | SYMFONY_MAILER_USERNAME: admin 23 | SYMFONY_MAILER_PASSWORD: admin 24 | SYMFONY_MAILER_FROM_ADDRESS: youremail@yourdomain.com 25 | SYMFONY_MAILER_SENDER_NAME: yourname 26 | COMPOSER_ALLOW_SUPERUSER: 1 27 | ports: 28 | - "80:80" 29 | volumes: 30 | - '.:/var/www' 31 | - '$HOME/.composer:/var/www/.composer' 32 | db: 33 | image: 'mysql:5.6' 34 | environment: 35 | MYSQL_ROOT_PASSWORD: root 36 | MYSQL_DATABASE: tania 37 | MYSQL_USER: tania 38 | MYSQL_PASSWORD: taniapass 39 | ports: 40 | - "3306:3306" 41 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2.2' 2 | 3 | services: 4 | app: 5 | image: tanibox/tania:latest 6 | 7 | -------------------------------------------------------------------------------- /docker/app/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM tanibox/php7-fpm-nginx-supervisord 2 | 3 | MAINTAINER Didiet Noor 4 | 5 | ARG BUILD_DATE 6 | 7 | LABEL org.label-schema.build-date=$BUILD_DATE \ 8 | org.label-schema.name="Tania Web Application" \ 9 | org.label-schema.description="Build artifact for Tania" \ 10 | org.label-schema.url="http://gettania.org/" \ 11 | org.label-schema.vcs-ref=$VCS_REF \ 12 | org.label-schema.vcs-url="https://github.com/Tanibox/tania.git" \ 13 | org.label-schema.vendor="Tania" \ 14 | org.label-schema.version="1.2-beta" \ 15 | org.label-schema.schema-version="1.0" 16 | 17 | ADD . /var/www 18 | COPY ./docker/app/nginx.conf /etc/nginx/nginx.conf 19 | COPY ./docker/app/tania-entrypoint /usr/local/bin/ 20 | VOLUME /var/www/var/cache 21 | WORKDIR /var/www 22 | 23 | EXPOSE 80 24 | 25 | RUN touch /var/www/.env \ 26 | && COMPOSER_ALLOW_SUPERUSER=1 composer install --no-autoloader --no-scripts --no-dev 27 | 28 | ENTRYPOINT [ "/usr/local/bin/tania-entrypoint" ] 29 | -------------------------------------------------------------------------------- /docker/app/nginx.conf: -------------------------------------------------------------------------------- 1 | user www-data; 2 | worker_processes 4; 3 | pid /run/nginx.pid; 4 | daemon off; 5 | 6 | events { 7 | worker_connections 2048; 8 | multi_accept on; 9 | use epoll; 10 | } 11 | 12 | http { 13 | server_tokens off; 14 | sendfile on; 15 | tcp_nopush on; 16 | tcp_nodelay on; 17 | keepalive_timeout 15; 18 | types_hash_max_size 2048; 19 | include /etc/nginx/mime.types; 20 | default_type application/octet-stream; 21 | access_log off; 22 | error_log off; 23 | gzip on; 24 | gzip_disable "msie6"; 25 | open_file_cache max=100; 26 | 27 | server { 28 | root /var/www/web; 29 | 30 | location / { 31 | try_files $uri @rewriteapp; 32 | } 33 | 34 | location @rewriteapp { 35 | rewrite ^(.*)$ /app.php/$1 last; 36 | } 37 | 38 | location ~ ^/(app|app_dev|config)\.php(/|$) { 39 | fastcgi_pass unix:/var/run/php-fpm.sock; 40 | fastcgi_split_path_info ^(.+\.php)(/.*)$; 41 | include fastcgi_params; 42 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 43 | fastcgi_param HTTPS off; 44 | } 45 | 46 | error_log /dev/stdout info; 47 | access_log /dev/stdout; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /docker/app/tania-entrypoint: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | composer install 5 | 6 | chown www-data:www-data -R /var/www/var/cache 7 | chown www-data:www-data -R /var/www/var/logs 8 | chown www-data:www-data -R /var/www/var/sessions 9 | 10 | 11 | if [ ! -d /tmp ]; then 12 | mkdir -p /tmp 13 | fi 14 | 15 | if [ ! -e /tmp/stdout ]; then 16 | mkfifo -m 666 /tmp/stdout 17 | fi 18 | 19 | cat <> /tmp/stdout 1>&2 & 20 | 21 | 22 | # Needed for Alpine 23 | /usr/bin/supervisord -n -c /etc/supervisord.conf 24 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | tests 18 | 19 | 20 | 21 | 22 | 23 | src 24 | 25 | src/*Bundle/Resources 26 | src/*/*Bundle/Resources 27 | src/*/Bundle/*Bundle/Resources 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /readme-assets/project-dashboard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/readme-assets/project-dashboard.jpg -------------------------------------------------------------------------------- /readme-assets/project-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/readme-assets/project-logo.png -------------------------------------------------------------------------------- /src/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | Require all denied 3 | 4 | 5 | Order deny,allow 6 | Deny from all 7 | 8 | -------------------------------------------------------------------------------- /src/AppBundle/AppBundle.php: -------------------------------------------------------------------------------- 1 | getRepository('AppBundle:Field')->findAll(); 19 | 20 | return $this->render('field/index.html.twig', array( 21 | 'fields' => $fields, 22 | 'classActive' => $_route, 23 | 'farms' => $fields 24 | )); 25 | } 26 | 27 | /** 28 | This method will render the new field submission form and handle the submission. 29 | */ 30 | public function createAction(Request $request, EntityManagerInterface $em, $_route) 31 | { 32 | // for the right bar menu 33 | $fields = $em->getRepository('AppBundle:Field')->findAll(); 34 | 35 | $field = new Field(); 36 | 37 | $form = $this->createForm(FieldType::class, $field); 38 | 39 | $form->handleRequest($request); 40 | 41 | if ($form->isSubmitted() && $form->isValid()) { 42 | $field = $form->getData(); 43 | 44 | // save to database here 45 | $field->setCreatedAt(new \DateTime('now')); 46 | 47 | $em->persist($field); 48 | $em->flush(); 49 | 50 | // redirect to dashboard and set the session variable with the new id 51 | return $this->redirectToRoute('fields_session', array('id' => $field->getId())); 52 | } 53 | 54 | return $this->render('field/add.html.twig', array( 55 | 'form' => $form->createView(), 56 | 'classActive' => $_route, 57 | 'farms' => $fields 58 | )); 59 | } 60 | 61 | /** 62 | and handle the data update when necessary. 63 | */ 64 | public function showAction($id, EntityManagerInterface $em, Request $request, $_route) 65 | { 66 | $field = $em->getRepository('AppBundle:Field')->find($id); 67 | 68 | $form = $this->createForm(FieldType::class, $field); 69 | 70 | $form->handleRequest($request); 71 | 72 | if ($form->isSubmitted() && $form->isValid()) { 73 | $field = $form->getData(); 74 | 75 | // save to database here 76 | $field->setUpdatedAt(new \DateTime('now')); 77 | 78 | $em->flush(); 79 | 80 | return $this->redirectToRoute('fields'); 81 | } 82 | 83 | // for the right bar menu 84 | $fields = $em->getRepository('AppBundle:Field')->findAll(); 85 | 86 | return $this->render('field/show.html.twig', array( 87 | 'form' => $form->createView(), 88 | 'classActive' => $_route, 89 | 'lat' => $field->getLat(), 90 | 'lng' => $field->getLng(), 91 | 'farms' => $fields 92 | )); 93 | } 94 | 95 | /** 96 | Set the current active farm for this session 97 | */ 98 | public function sessionAction($id) 99 | { 100 | $this->get('session')->set('activeFarm', $id); 101 | return $this->redirectToRoute('dashboard'); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/AppBundle/Controller/InventoryController.php: -------------------------------------------------------------------------------- 1 | getRepository('AppBundle:Seed')->findAll(); 16 | 17 | // for the right bar menu 18 | $fields = $em->getRepository('AppBundle:Field')->findAll(); 19 | 20 | return $this->render('inventory/index.html.twig', array( 21 | 'seeds' => $seeds, 22 | 'classActive' => $_route, 23 | 'farms' => $fields 24 | )); 25 | } 26 | 27 | public function seedCreateAction(Request $request, EntityManagerInterface $em, $_route) 28 | { 29 | $seed = new Seed(); 30 | 31 | $form = $this->createForm(SeedType::class, $seed); 32 | 33 | $form->handleRequest($request); 34 | 35 | if ($form->isSubmitted() && $form->isValid()) { 36 | $seed = $form->getData(); 37 | 38 | // save to database here 39 | $seed->setCreatedAt(new \DateTime('now')); 40 | 41 | $em->persist($seed); 42 | $em->flush(); 43 | 44 | return $this->redirectToRoute('inventories'); 45 | } 46 | 47 | // for the right bar menu 48 | $fields = $em->getRepository('AppBundle:Field')->findAll(); 49 | 50 | return $this->render('seed/create.html.twig', array( 51 | 'form' => $form->createView(), 52 | 'classActive' => $_route, 53 | 'farms' => $fields 54 | )); 55 | } 56 | 57 | public function seedEditAction($id, $_route, Request $request, EntityManagerInterface $em) 58 | { 59 | $seed = $em->getRepository('AppBundle:Seed')->find($id); 60 | 61 | $form = $this->createForm(SeedType::class, $seed); 62 | 63 | $form->handleRequest($request); 64 | 65 | if ($form->isSubmitted() && $form->isValid()) { 66 | $seed = $form->getData(); 67 | 68 | // save to database here 69 | $seed->setUpdatedAt(new \DateTime('now')); 70 | 71 | $em->persist($seed); 72 | $em->flush(); 73 | 74 | return $this->redirectToRoute('inventories'); 75 | } 76 | 77 | // for the right bar menu 78 | $fields = $em->getRepository('AppBundle:Field')->findAll(); 79 | 80 | return $this->render('seed/edit.html.twig', array( 81 | 'form' => $form->createView(), 82 | 'seed' => $seed, 83 | 'classActive' => $_route, 84 | 'farms' => $fields 85 | )); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/AppBundle/Controller/ProfileController.php: -------------------------------------------------------------------------------- 1 | getUser(); 23 | if (!is_object($user) || !$user instanceof UserInterface) { 24 | throw new AccessDeniedException('This user does not have access to this section.'); 25 | } 26 | 27 | /** @var $dispatcher EventDispatcherInterface */ 28 | $dispatcher = $this->get('event_dispatcher'); 29 | 30 | $event = new GetResponseUserEvent($user, $request); 31 | $dispatcher->dispatch(FOSUserEvents::PROFILE_EDIT_INITIALIZE, $event); 32 | 33 | if (null !== $event->getResponse()) { 34 | return $event->getResponse(); 35 | } 36 | 37 | /** @var $formFactory FactoryInterface */ 38 | $formFactory = $this->get('fos_user.profile.form.factory'); 39 | 40 | $form = $formFactory->createForm(); 41 | $form->setData($user); 42 | 43 | $form->handleRequest($request); 44 | 45 | if ($form->isSubmitted() && $form->isValid()) { 46 | /** @var $userManager UserManagerInterface */ 47 | $userManager = $this->get('fos_user.user_manager'); 48 | 49 | $event = new FormEvent($form, $request); 50 | $dispatcher->dispatch(FOSUserEvents::PROFILE_EDIT_SUCCESS, $event); 51 | 52 | $userManager->updateUser($user); 53 | 54 | if (null === $response = $event->getResponse()) { 55 | $url = $this->generateUrl('fos_user_profile_show'); 56 | $response = new RedirectResponse($url); 57 | } 58 | 59 | $dispatcher->dispatch(FOSUserEvents::PROFILE_EDIT_COMPLETED, new FilterUserResponseEvent($user, $request, $response)); 60 | 61 | return $response; 62 | } 63 | 64 | return $this->render('@FOSUser/Profile/edit.html.twig', array( 65 | 'form' => $form->createView(), 66 | 'classActive' => 'fos_user_profile_edit' 67 | )); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/AppBundle/Controller/RegistrationController.php: -------------------------------------------------------------------------------- 1 | 21 | * @author Christophe Coevoet 22 | */ 23 | class RegistrationController extends BaseController 24 | { 25 | /** 26 | * @param Request $request 27 | * 28 | * @return Response 29 | */ 30 | public function registerAction(Request $request) 31 | { 32 | /** @var $formFactory FactoryInterface */ 33 | $formFactory = $this->get('fos_user.registration.form.factory'); 34 | /** @var $userManager UserManagerInterface */ 35 | $userManager = $this->get('fos_user.user_manager'); 36 | /** @var $dispatcher EventDispatcherInterface */ 37 | $dispatcher = $this->get('event_dispatcher'); 38 | 39 | $user = $userManager->createUser(); 40 | $user->setEnabled(true); 41 | 42 | $event = new GetResponseUserEvent($user, $request); 43 | $dispatcher->dispatch(FOSUserEvents::REGISTRATION_INITIALIZE, $event); 44 | 45 | if (null !== $event->getResponse()) { 46 | return $event->getResponse(); 47 | } 48 | 49 | $form = $formFactory->createForm(); 50 | $form->setData($user); 51 | 52 | $form->handleRequest($request); 53 | 54 | if ($form->isSubmitted()) { 55 | if ($form->isValid()) { 56 | $event = new FormEvent($form, $request); 57 | $dispatcher->dispatch(FOSUserEvents::REGISTRATION_SUCCESS, $event); 58 | 59 | $userManager->updateUser($user); 60 | 61 | if (null === $response = $event->getResponse()) { 62 | $url = $this->generateUrl('dashboard'); 63 | $response = new RedirectResponse($url); 64 | } 65 | 66 | $dispatcher->dispatch(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, $response)); 67 | 68 | return $response; 69 | } 70 | 71 | $event = new FormEvent($form, $request); 72 | $dispatcher->dispatch(FOSUserEvents::REGISTRATION_FAILURE, $event); 73 | 74 | if (null !== $response = $event->getResponse()) { 75 | return $response; 76 | } 77 | } 78 | 79 | return $this->render('@FOSUser/Registration/register.html.twig', array( 80 | 'form' => $form->createView(), 81 | )); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/AppBundle/Controller/ReservoirController.php: -------------------------------------------------------------------------------- 1 | get('session')->get('activeFarm'); 16 | 17 | $reservoir = new Reservoir(); 18 | $reservoirs = $em->getRepository('AppBundle:Reservoir')->findByField($activeFarmId); 19 | 20 | $form = $this->createForm(ReservoirType::class, $reservoir); 21 | $form->handleRequest($request); 22 | 23 | if ($form->isSubmitted() && $form->isValid()) { 24 | $reservoir = $form->getData(); 25 | 26 | // save to database here 27 | $reservoir->setCreatedAt(new \DateTime('now')); 28 | 29 | $em->persist($reservoir); 30 | $em->flush(); 31 | 32 | return $this->redirectToRoute('reservoirs'); 33 | } 34 | 35 | // for the right bar menu 36 | $fields = $em->getRepository('AppBundle:Field')->findAll(); 37 | 38 | return $this->render('reservoir/index.html.twig', array( 39 | 'form' => $form->createView(), 40 | 'reservoirs' => $reservoirs, 41 | 'classActive' => $_route, 42 | 'farms' => $fields 43 | )); 44 | } 45 | 46 | public function showAction($id, $_route, EntityManagerInterface $em, Request $request) 47 | { 48 | $reservoir = $em->getRepository('AppBundle:Reservoir')->find($id); 49 | 50 | $form = $this->createForm(ReservoirType::class, $reservoir); 51 | 52 | $form->handleRequest($request); 53 | 54 | if ($form->isSubmitted() && $form->isValid()) { 55 | $reservoir = $form->getData(); 56 | 57 | // save to database here 58 | $reservoir->setUpdatedAt(new \DateTime('now')); 59 | 60 | $em->flush(); 61 | 62 | return $this->redirectToRoute('reservoirs'); 63 | } 64 | 65 | // for the right bar menu 66 | $fields = $em->getRepository('AppBundle:Field')->findAll(); 67 | 68 | return $this->render('reservoir/show.html.twig', array( 69 | 'form' => $form->createView(), 70 | 'reservoir' => $reservoir, 71 | 'classActive' => $_route, 72 | 'farms' => $fields 73 | )); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/AppBundle/Controller/SettingsController.php: -------------------------------------------------------------------------------- 1 | getRepository('AppBundle:Setting')->findBy(array('key' => array('mqtt_host', 'mqtt_port'))); 16 | 17 | $form = $this->createForm(SettingType::class, array('mqttHost' => $mqtt[0]->getValue(), 'mqttPort' => $mqtt[1]->getValue())); 18 | $form->handleRequest($request); 19 | 20 | if ($form->isSubmitted() && $form->isValid()) { 21 | $data = $form->getData(); 22 | 23 | // save to database 24 | $mqttHost = $em->getRepository('AppBundle:Setting')->findOneBy(array('key' => 'mqtt_host')); 25 | $mqttHost->setValue($data['mqttHost']); 26 | $mqttHost->setUpdatedAt(new \DateTime('now')); 27 | $em->persist($mqttHost); 28 | 29 | $mqttPort = $em->getRepository('AppBundle:Setting')->findOneBy(array('key' => 'mqtt_port')); 30 | $mqttPort->setValue($data['mqttPort']); 31 | $mqttPort->setUpdatedAt(new \DateTime('now')); 32 | $em->persist($mqttPort); 33 | 34 | $em->flush(); 35 | 36 | return $this->redirectToRoute('settings'); 37 | } 38 | 39 | // for the right bar menu 40 | $fields = $em->getRepository('AppBundle:Field')->findAll(); 41 | 42 | return $this->render('settings/index.html.twig', array( 43 | 'classActive' => $_route, 44 | 'farms' => $fields, 45 | 'form' => $form->createView() 46 | )); 47 | } 48 | } -------------------------------------------------------------------------------- /src/AppBundle/Controller/TaskController.php: -------------------------------------------------------------------------------- 1 | get('session')->get('activeFarm'); 16 | 17 | $tasks = $em->getRepository('AppBundle:Task')->findByField($activeFarmId); 18 | 19 | // for the right bar menu 20 | $fields = $em->getRepository('AppBundle:Field')->findAll(); 21 | 22 | return $this->render('task/index.html.twig', array( 23 | 'tasks' => $tasks, 24 | 'classActive' => $_route, 25 | 'farms' => $fields 26 | )); 27 | } 28 | 29 | public function createAction(Request $request, EntityManagerInterface $em, $_route) 30 | { 31 | $activeFarmId = $this->get('session')->get('activeFarm'); 32 | 33 | $task = new Task(); 34 | 35 | $form = $this->createForm(TaskType::class, $task); 36 | 37 | $form->handleRequest($request); 38 | 39 | if ($form->isSubmitted() && $form->isValid()) { 40 | $task = $form->getData(); 41 | 42 | // save to database here 43 | $field = $em->getRepository('AppBundle:Field')->findOneById($activeFarmId); 44 | $task->setField($field); 45 | $task->setCreatedAt(new \DateTime('now')); 46 | 47 | $em->persist($task); 48 | $em->flush(); 49 | 50 | return $this->redirectToRoute('tasks'); 51 | } 52 | 53 | // for the right bar menu 54 | $fields = $em->getRepository('AppBundle:Field')->findAll(); 55 | 56 | return $this->render('task/create.html.twig', array( 57 | 'form' => $form->createView(), 58 | 'classActive' => $_route, 59 | 'farms' => $fields 60 | )); 61 | } 62 | 63 | public function showAction($id, Request $request, EntityManagerInterface $em, $_route) 64 | { 65 | $task = $em->getRepository('AppBundle:Task')->find($id); 66 | 67 | $form = $this->createForm(TaskType::class, $task); 68 | 69 | $form->handleRequest($request); 70 | 71 | if ($form->isSubmitted() && $form->isValid()) { 72 | $task = $form->getData(); 73 | 74 | // save to database here 75 | $task->setUpdatedAt(new \DateTime('now')); 76 | 77 | $em->flush(); 78 | 79 | return $this->redirectToRoute('tasks'); 80 | } 81 | 82 | // for the right bar menu 83 | $fields = $em->getRepository('AppBundle:Field')->findAll(); 84 | 85 | return $this->render('task/show.html.twig', array( 86 | 'form' => $form->createView(), 87 | 'classActive' => $_route, 88 | 'farms' => $fields 89 | )); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/AppBundle/Data/CategoryMaster.php: -------------------------------------------------------------------------------- 1 | 'NFT', 11 | 2 => 'Drip Irrigation', 12 | 3 => 'Ebb and Flow', 13 | 4 => 'Soil/Organic', 14 | ); 15 | } 16 | 17 | public static function areaUnits() 18 | { 19 | return array( 20 | 1 => 'Holes', 21 | 2 => 'Trays', 22 | ); 23 | } 24 | 25 | public static function seedUnits() 26 | { 27 | return array( 28 | 1 => 'seeds', 29 | 2 => 'gr', 30 | 3 => 'kg', 31 | 4 => 'lbs', 32 | 5 => 'oz', 33 | ); 34 | } 35 | 36 | public static function deviceType() 37 | { 38 | return array( 39 | 1 => 'Xiaomi Flora', 40 | 2 => 'Raspberry Pi', 41 | 3 => 'Arduino', 42 | 4 => 'ESP8266', 43 | 5 => 'Other' 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/AppBundle/DataFixtures/ORM/LoadResourceData.php: -------------------------------------------------------------------------------- 1 | setType('Temperature'); 14 | $resource->setCreatedAt(new \DateTime('now')); 15 | $manager->persist($resource); 16 | 17 | $resource = new Resource(); 18 | $resource->setType('Humidity'); 19 | $resource->setCreatedAt(new \DateTime('now')); 20 | $manager->persist($resource); 21 | 22 | $resource = new Resource(); 23 | $resource->setType('Light'); 24 | $resource->setCreatedAt(new \DateTime('now')); 25 | $manager->persist($resource); 26 | 27 | $resource = new Resource(); 28 | $resource->setType('Nutrition'); 29 | $resource->setCreatedAt(new \DateTime('now')); 30 | $manager->persist($resource); 31 | 32 | $resource = new Resource(); 33 | $resource->setType('Moisture'); 34 | $resource->setCreatedAt(new \DateTime('now')); 35 | $manager->persist($resource); 36 | 37 | $resource = new Resource(); 38 | $resource->setType('pH'); 39 | $resource->setCreatedAt(new \DateTime('now')); 40 | $manager->persist($resource); 41 | 42 | $resource = new Resource(); 43 | $resource->setType('On/Off State'); 44 | $resource->setCreatedAt(new \DateTime('now')); 45 | $manager->persist($resource); 46 | 47 | $resource = new Resource(); 48 | $resource->setType('Custom'); 49 | $resource->setCreatedAt(new \DateTime('now')); 50 | $manager->persist($resource); 51 | 52 | $manager->flush(); 53 | } 54 | } -------------------------------------------------------------------------------- /src/AppBundle/DataFixtures/ORM/LoadSeedCategory.php: -------------------------------------------------------------------------------- 1 | setName('Herb'); 14 | $category->setSlug('herb'); 15 | $category->setCreatedAt(new \DateTime('now')); 16 | $manager->persist($category); 17 | 18 | $category = new SeedCategory(); 19 | $category->setName('Vegetable'); 20 | $category->setSlug('vegetable'); 21 | $category->setCreatedAt(new \DateTime('now')); 22 | $manager->persist($category); 23 | 24 | $category = new SeedCategory(); 25 | $category->setName('Sprout/Microgreens'); 26 | $category->setSlug('sprout-microgreens'); 27 | $category->setCreatedAt(new \DateTime('now')); 28 | $manager->persist($category); 29 | 30 | $category = new SeedCategory(); 31 | $category->setName('Fruit'); 32 | $category->setSlug('fruit'); 33 | $category->setCreatedAt(new \DateTime('now')); 34 | $manager->persist($category); 35 | 36 | $category = new SeedCategory(); 37 | $category->setName('Tubber'); 38 | $category->setSlug('tubber'); 39 | $category->setCreatedAt(new \DateTime('now')); 40 | $manager->persist($category); 41 | 42 | $category = new SeedCategory(); 43 | $category->setName('Flower'); 44 | $category->setSlug('flower'); 45 | $category->setCreatedAt(new \DateTime('now')); 46 | $manager->persist($category); 47 | 48 | $category = new SeedCategory(); 49 | $category->setName('Other'); 50 | $category->setSlug('other'); 51 | $category->setCreatedAt(new \DateTime('now')); 52 | $manager->persist($category); 53 | 54 | $manager->flush(); 55 | } 56 | } -------------------------------------------------------------------------------- /src/AppBundle/DataFixtures/ORM/LoadUserData.php: -------------------------------------------------------------------------------- 1 | container = $container; 20 | } 21 | 22 | public function load(ObjectManager $manager) 23 | { 24 | $userManager = $this->container->get('fos_user.user_manager'); 25 | 26 | $email_exist = $userManager->findUserByEmail('test@test.id'); 27 | 28 | // Check if the user exists to prevent Integrity constraint violation error in the insertion 29 | if($email_exist){ 30 | return false; 31 | } 32 | 33 | $user = $userManager->createUser(); 34 | $user->setUsername('testuser'); 35 | $user->setEmail('test@test.id'); 36 | $user->setEnabled(true); 37 | $user->setPlainPassword('test123'); 38 | 39 | $userManager->updateUser($user); 40 | } 41 | } -------------------------------------------------------------------------------- /src/AppBundle/DoctrineExtensions/Utils/AnyValue.php: -------------------------------------------------------------------------------- 1 | match(Lexer::T_IDENTIFIER); 17 | $parser->match(Lexer::T_OPEN_PARENTHESIS); 18 | $this->value = $parser->StringPrimary(); 19 | $parser->match(Lexer::T_CLOSE_PARENTHESIS); 20 | } 21 | 22 | public function getSql(SqlWalker $sqlWalker) 23 | { 24 | return 'ANY_VALUE('.$this->value->dispatch($sqlWalker).')'; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/AppBundle/Entity/AreasDevices.php: -------------------------------------------------------------------------------- 1 | id; 58 | } 59 | 60 | /** 61 | * Set updatedAt 62 | * 63 | * @param \DateTime $updatedAt 64 | * 65 | * @return AreasDevices 66 | */ 67 | public function setUpdatedAt($updatedAt) 68 | { 69 | $this->updatedAt = $updatedAt; 70 | 71 | return $this; 72 | } 73 | 74 | /** 75 | * Get updatedAt 76 | * 77 | * @return \DateTime 78 | */ 79 | public function getUpdatedAt() 80 | { 81 | return $this->updatedAt; 82 | } 83 | 84 | /** 85 | * Set createdAt 86 | * 87 | * @param \DateTime $createdAt 88 | * 89 | * @return AreasDevices 90 | */ 91 | public function setCreatedAt($createdAt) 92 | { 93 | $this->createdAt = $createdAt; 94 | 95 | return $this; 96 | } 97 | 98 | /** 99 | * Get createdAt 100 | * 101 | * @return \DateTime 102 | */ 103 | public function getCreatedAt() 104 | { 105 | return $this->createdAt; 106 | } 107 | 108 | /** 109 | * Set area 110 | * 111 | * @param \AppBundle\Entity\Area $area 112 | * 113 | * @return AreasDevices 114 | */ 115 | public function setArea(\AppBundle\Entity\Area $area = null) 116 | { 117 | $this->area = $area; 118 | 119 | return $this; 120 | } 121 | 122 | /** 123 | * Get area 124 | * 125 | * @return \AppBundle\Entity\Area 126 | */ 127 | public function getArea() 128 | { 129 | return $this->area; 130 | } 131 | 132 | /** 133 | * Set device 134 | * 135 | * @param \AppBundle\Entity\Device $device 136 | * 137 | * @return AreasDevices 138 | */ 139 | public function setDevice(\AppBundle\Entity\Device $device = null) 140 | { 141 | $this->device = $device; 142 | 143 | return $this; 144 | } 145 | 146 | /** 147 | * Get device 148 | * 149 | * @return \AppBundle\Entity\Device 150 | */ 151 | public function getDevice() 152 | { 153 | return $this->device; 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/AppBundle/Entity/Setting.php: -------------------------------------------------------------------------------- 1 | id; 46 | } 47 | 48 | /** 49 | * Set key 50 | * 51 | * @param string $key 52 | * 53 | * @return Setting 54 | */ 55 | public function setKey($key) 56 | { 57 | $this->key = $key; 58 | 59 | return $this; 60 | } 61 | 62 | /** 63 | * Get key 64 | * 65 | * @return string 66 | */ 67 | public function getKey() 68 | { 69 | return $this->key; 70 | } 71 | 72 | /** 73 | * Set value 74 | * 75 | * @param string $value 76 | * 77 | * @return Setting 78 | */ 79 | public function setValue($value) 80 | { 81 | $this->value = $value; 82 | 83 | return $this; 84 | } 85 | 86 | /** 87 | * Get value 88 | * 89 | * @return string 90 | */ 91 | public function getValue() 92 | { 93 | return $this->value; 94 | } 95 | 96 | /** 97 | * Set updatedAt 98 | * 99 | * @param \DateTime $updatedAt 100 | * 101 | * @return Setting 102 | */ 103 | public function setUpdatedAt($updatedAt) 104 | { 105 | $this->updatedAt = $updatedAt; 106 | 107 | return $this; 108 | } 109 | 110 | /** 111 | * Get updatedAt 112 | * 113 | * @return \DateTime 114 | */ 115 | public function getUpdatedAt() 116 | { 117 | return $this->updatedAt; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/AppBundle/Entity/User.php: -------------------------------------------------------------------------------- 1 | add('area', EntityType::class, array( 15 | 'class' => 'AppBundle:Area', 16 | 'choice_label' => 'name', 17 | 'required' => true, 18 | 'label' => 'Area Name', 19 | 'translation_domain' => 'dashboard' 20 | )) 21 | ->add('save', SubmitType::class, array( 22 | 'label' => 'Add Area', 23 | 'translation_domain' => 'dashboard' 24 | )); 25 | } 26 | } -------------------------------------------------------------------------------- /src/AppBundle/Form/AreaType.php: -------------------------------------------------------------------------------- 1 | add('name', TextType::class, array( 21 | 'attr' => array('maxlength' => 50), 22 | 'label' => 'Name', 23 | 'translation_domain' => 'dashboard')) 24 | ->add('reservoir', EntityType::class, array( 25 | 'class' => 'AppBundle:Reservoir', 26 | 'choice_label' => 'name', 27 | 'required' => false, 28 | 'label' => 'Reservoir', 29 | 'translation_domain' => 'dashboard' 30 | )) 31 | ->add('growingMethod', ChoiceType::class, array( 32 | 'choices' => array( 33 | CategoryMaster::growingMethods()[1] => 1, 34 | CategoryMaster::growingMethods()[2] => 2, 35 | CategoryMaster::growingMethods()[3] => 3, 36 | CategoryMaster::growingMethods()[4] => 4, 37 | ), 38 | 'label' => 'Growing method', 39 | 'translation_domain' => 'dashboard' 40 | )) 41 | ->add('capacity', IntegerType::class, array( 42 | 'label' => 'Capacity', 43 | 'translation_domain' => 'dashboard' 44 | )) 45 | ->add('measurementUnit', ChoiceType::class, array( 46 | 'choices' => array( 47 | CategoryMaster::areaUnits()[1] => 1, 48 | CategoryMaster::areaUnits()[2] => 2, 49 | ), 50 | 'label' => 'Measurement unit', 51 | 'translation_domain' => 'dashboard' 52 | )) 53 | ->add('imageFile', VichImageType::class, array( 54 | 'required' => false, 55 | 'allow_delete' => true, 56 | 'image_uri' => true, 57 | 'download_uri' => true, 58 | 'label' => 'Image file', 59 | 'translation_domain' => 'dashboard' 60 | )) 61 | ->add('save', SubmitType::class, array( 62 | 'label' => 'Save', 63 | 'translation_domain' => 'dashboard' 64 | )); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/AppBundle/Form/DeviceType.php: -------------------------------------------------------------------------------- 1 | add('name', TextType::class, array( 18 | 'attr' => array('maxlength' => 50), 19 | 'label' => 'Name', 20 | 'translation_domain' => 'dashboard' 21 | )) 22 | ->add('description', TextareaType::class, array( 23 | 'required' => false, 24 | 'label' => 'Description', 25 | 'translation_domain' => 'dashboard' 26 | )) 27 | ->add('deviceType', ChoiceType::class, array( 28 | 'choices' => array( 29 | CategoryMaster::deviceType()[1] => 1, 30 | CategoryMaster::deviceType()[2] => 2, 31 | CategoryMaster::deviceType()[3] => 3, 32 | CategoryMaster::deviceType()[4] => 4 33 | ), 34 | 'label' => 'Device type', 35 | 'required' => true, 36 | 'translation_domain' => 'dashboard' 37 | )) 38 | ->add('save', SubmitType::class, array( 39 | 'label' => 'Add Device', 40 | 'translation_domain' => 'dashboard' 41 | )); 42 | } 43 | } -------------------------------------------------------------------------------- /src/AppBundle/Form/FieldType.php: -------------------------------------------------------------------------------- 1 | add('name', TextType::class, array( 19 | 'attr' => array('maxlength' => 50), 20 | 'label' => 'Name', 21 | 'translation_domain' => 'dashboard')) 22 | ->add('lat', NumberType::class, array( 23 | 'required' => false, 24 | 'scale' => 8, 25 | 'label' => 'Latitude', 26 | 'translation_domain' => 'dashboard')) 27 | ->add('lng', NumberType::class, array( 28 | 'required' => false, 29 | 'scale' => 8, 30 | 'label' => 'Longitude', 31 | 'translation_domain' => 'dashboard')) 32 | ->add('description', TextareaType::class, array( 33 | 'required' => false, 34 | 'label' => 'Description', 35 | 'translation_domain' => 'dashboard')) 36 | ->add('imageFile', VichImageType::class, array( 37 | 'required' => false, 38 | 'allow_delete' => true, 39 | 'image_uri' => true, 40 | 'download_uri' => true, 41 | 'label' => 'Image file', 42 | 'translation_domain' => 'dashboard' 43 | )) 44 | ->add('save', SubmitType::class, array( 45 | 'label' => 'Save', 46 | 'translation_domain' => 'dashboard')); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/AppBundle/Form/PlantHarvestType.php: -------------------------------------------------------------------------------- 1 | add('action', ChoiceType::class, array( 17 | 'choices' => array('Harvest' => 'harvest', 'Dispose' => 'dispose'), 18 | 'expanded' => true, 19 | 'label' => 'Action', 20 | 'translation_domain' => 'dashboard' 21 | )) 22 | ->add('note', TextareaType::class, array( 23 | 'required' => false, 24 | 'label' => 'Note', 25 | 'translation_domain' => 'dashboard')) 26 | ->add('save', SubmitType::class, array( 27 | 'label' => 'Update', 28 | 'translation_domain' => 'dashboard')); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/AppBundle/Form/PlantType.php: -------------------------------------------------------------------------------- 1 | setDefaults([ 19 | 'entityManager' => null, 20 | ]); 21 | } 22 | 23 | public function buildForm(FormBuilderInterface $builder, array $options) 24 | { 25 | $builder 26 | ->add('area', EntityType::class, array( 27 | 'class' => 'AppBundle:Area', 28 | 'choice_label' => function ($area) use ($options) { 29 | // measurement unit for area capacity 30 | $unit = CategoryMaster::areaUnits()[$area->getMeasurementUnit()]; 31 | 32 | // capacity left 33 | $areasInfo = $options['entityManager']->getRepository('AppBundle:Plant')->findBy(array('area' => $area->getId())); 34 | $usedArea = array_reduce($areasInfo, function ($carry, $item) { 35 | return $carry += $item->getAreaCapacity(); 36 | }); 37 | $areaLeft = $area->getCapacity() - $usedArea; 38 | 39 | return $area->getName().' (Capacities: '.$areaLeft.' '.$unit.' remaining)'; 40 | }, 41 | 'label' => 'Area', 42 | 'translation_domain' => 'dashboard' 43 | )) 44 | ->add('seed', EntityType::class, array( 45 | 'class' => 'AppBundle:Seed', 46 | 'choice_label' => function ($seed) use ($options) { 47 | // measurement unit for seed amount 48 | $unit = CategoryMaster::seedUnits()[$seed->getMeasurementUnit()]; 49 | 50 | // seeds left 51 | $seedsInfo = $options['entityManager']->getRepository('AppBundle:Plant')->findBy(array('seed' => $seed->getId())); 52 | 53 | $usedSeed = array_reduce($seedsInfo, function ($carry, $item) { 54 | return $carry += $item->getAreaCapacity(); 55 | }); 56 | $seedLeft = $seed->getQuantity() - $usedSeed; 57 | 58 | return $seed->getName().' (Quantities: '.$seedLeft.' '.$unit.' remaining)'; 59 | }, 60 | 'label' => 'Seed', 61 | 'translation_domain' => 'dashboard' 62 | )) 63 | ->add('seedlingDate', DateType::class, array( 64 | 'years' => range(date('Y'), date('Y') - 1), 65 | 'widget' => 'single_text', 66 | 'label' => 'Seedling date', 67 | 'translation_domain' => 'dashboard' 68 | )) 69 | ->add('areaCapacity', IntegerType::class, array( 70 | 'label' => 'Area capacity', 71 | 'translation_domain' => 'dashboard' 72 | )) 73 | ->add('save', SubmitType::class, array( 74 | 'label' => 'Save', 75 | 'translation_domain' => 'dashboard')); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/AppBundle/Form/RegistrationFormType.php: -------------------------------------------------------------------------------- 1 | add('plainPassword', LegacyFormHelper::getType('Symfony\Component\Form\Extension\Core\Type\RepeatedType'), array( 14 | 'type' => LegacyFormHelper::getType('Symfony\Component\Form\Extension\Core\Type\PasswordType'), 15 | 'options' => array('translation_domain' => 'FOSUserBundle', 'attr' => array('class' => 'form-control')), 16 | 'first_options' => array('label' => 'form.password'), 17 | 'second_options' => array('label' => 'form.password_confirmation'), 18 | 'invalid_message' => 'fos_user.password.mismatch', 19 | )); 20 | } 21 | 22 | public function getParent() 23 | { 24 | return 'FOS\UserBundle\Form\Type\RegistrationFormType'; 25 | } 26 | 27 | public function getBlockPrefix() 28 | { 29 | return 'app_user_registration'; 30 | } 31 | 32 | // For Symfony 2.x 33 | public function getName() 34 | { 35 | return $this->getBlockPrefix(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/AppBundle/Form/ReservoirType.php: -------------------------------------------------------------------------------- 1 | add('name', TextType::class, array( 19 | 'label' => 'Name', 20 | 'translation_domain' => 'dashboard' 21 | )) 22 | ->add('field', EntityType::class, array( 23 | 'class' => 'AppBundle:Field', 24 | 'choice_label' => 'name', 25 | 'label' => 'Field', 26 | 'translation_domain' => 'dashboard' 27 | )) 28 | ->add('capacity', NumberType::class, array( 29 | 'scale' => 2, 30 | 'label' => 'Capacity', 31 | 'translation_domain' => 'dashboard' 32 | )) 33 | ->add('measurementUnit', ChoiceType::class, array( 34 | 'choices' => array( 35 | 'Litre' => 1, 36 | 'Gallon' => 2, 37 | ), 38 | 'label' => 'Measurement unit', 39 | 'translation_domain' => 'dashboard' 40 | )) 41 | ->add('save', SubmitType::class, array( 42 | 'label' => 'Save', 43 | 'translation_domain' => 'dashboard' 44 | )); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/AppBundle/Form/ResourceDeviceType.php: -------------------------------------------------------------------------------- 1 | add('name', TextType::class, array( 20 | 'attr' => array('maxlength' => 50), 21 | 'label' => 'Name', 22 | 'translation_domain' => 'dashboard' 23 | )) 24 | ->add('description', TextareaType::class, array( 25 | 'required' => false, 26 | 'label' => 'Description', 27 | 'translation_domain' => 'dashboard' 28 | )) 29 | ->add('rid', TextType::class, array( 30 | 'attr' => array('maxlength' => 50), 31 | 'label' => 'Resource ID', 32 | 'translation_domain' => 'dashboard' 33 | )) 34 | ->add('resource', EntityType::class, array( 35 | 'class' => 'AppBundle:Resource', 36 | 'choice_label' => 'type', 37 | 'required' => true, 38 | 'label' => 'Resource Type', 39 | 'translation_domain' => 'dashboard' 40 | )) 41 | ->add('dataType', ChoiceType::class, array( 42 | 'choices' => array( 43 | 'Float' => 'Float', 44 | 'Integer' => 'Integer', 45 | 'Boolean' => 'Boolean', 46 | 'String' => 'String' 47 | ), 48 | 'label' => 'Data Type', 49 | 'translation_domain' => 'dashboard' 50 | )) 51 | ->add('unit', ChoiceType::class, array( 52 | 'choices' => array( 53 | 'Celcius' => 'Celcius', 54 | 'Fahrenheit' => 'Fahrenheit', 55 | 'uS/cm' => 'uS/cm', 56 | 'Lux' => 'Lux', 57 | '%' => '%', 58 | 'None' => 'None' 59 | ), 60 | 'label' => 'Unit', 61 | 'translation_domain' => 'dashboard' 62 | )) 63 | ->add('save', SubmitType::class, array( 64 | 'label' => 'Add Resource', 65 | 'translation_domain' => 'dashboard' 66 | )); 67 | } 68 | } -------------------------------------------------------------------------------- /src/AppBundle/Form/SettingType.php: -------------------------------------------------------------------------------- 1 | add('mqttHost', TextType::class, array( 15 | 'attr' => array('maxlength' => 200), 16 | 'label' => 'MQTT Host', 17 | 'translation_domain' => 'dashboard' 18 | )) 19 | ->add('mqttPort', TextType::class, array( 20 | 'attr' => array('maxlength' => 200), 21 | 'label' => 'MQTT Port', 22 | 'translation_domain' => 'dashboard' 23 | )) 24 | ->add('save', SubmitType::class, array( 25 | 'label' => 'Save', 26 | 'translation_domain' => 'dashboard' 27 | )); 28 | } 29 | } -------------------------------------------------------------------------------- /src/AppBundle/Form/TaskType.php: -------------------------------------------------------------------------------- 1 | add('name', TextType::class, array( 19 | 'label' => 'Name', 20 | 'translation_domain' => 'dashboard' 21 | )) 22 | ->add('notes', TextareaType::class, array( 23 | 'required' => false, 24 | 'label' => 'Note', 25 | 'translation_domain' => 'dashboard' 26 | )) 27 | ->add('category', ChoiceType::class, array( 28 | 'choices' => array( 29 | 'Area' => 'area', 30 | 'Plant' => 'plant', 31 | 'Seed' => 'seed', 32 | 'Reservoir' => 'reservoir', 33 | ), 34 | 'label' => 'Category', 35 | 'translation_domain' => 'dashboard' 36 | )) 37 | ->add('dueDate', DateTimeType::class, array( 38 | 'years' => range(date('Y'), date('Y') + 1), 39 | 'widget' => 'single_text', 40 | 'label' => 'Due date', 41 | 'translation_domain' => 'dashboard' 42 | )) 43 | ->add('urgencyLevel', ChoiceType::class, array( 44 | 'choices' => array( 45 | 'Low' => 'low', 46 | 'Medium' => 'medium', 47 | 'High' => 'high', 48 | ), 49 | 'label' => 'Level of urgency', 50 | 'translation_domain' => 'dashboard' 51 | )) 52 | ->add('isDone', ChoiceType::class, array( 53 | 'choices' => array( 54 | 'No' => 0, 55 | 'Yes' => 1, 56 | ), 57 | 'label' => 'Is it done?', 58 | 'translation_domain' => 'dashboard' 59 | )) 60 | ->add('save', SubmitType::class, array( 61 | 'label' => 'Save', 62 | 'translation_domain' => 'dashboard' 63 | )); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/AppBundle/Repository/AbstractRepository.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | abstract class AbstractRepository 12 | { 13 | /** 14 | * @var EntityManager 15 | */ 16 | private $manager; 17 | 18 | /** 19 | * @var string 20 | */ 21 | private $class; 22 | 23 | /** 24 | * @param EntityManager $entityManager 25 | * @param string $class 26 | */ 27 | public function __construct(EntityManager $entityManager, $class) 28 | { 29 | $this->manager = $entityManager; 30 | $this->class = $class; 31 | } 32 | 33 | /** 34 | * @return EntityRepository 35 | */ 36 | protected function getRepository() 37 | { 38 | return $this->manager->getRepository($this->class); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/AppBundle/Repository/TaskRepository.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class TaskRepository extends AbstractRepository 11 | { 12 | /** 13 | * @param int $limit 14 | * @param int $farmId 15 | * 16 | * @return Task[] 17 | */ 18 | public function deadlineTasks($farmId, $limit = 9) 19 | { 20 | $qb = $this->getRepository()->createQueryBuilder('t'); 21 | 22 | $query = $qb 23 | ->select('t') 24 | ->orderBy('t.dueDate', 'ASC') 25 | ->where('t.isDone = 0') 26 | ->andWhere('t.field = '.$farmId) 27 | ->setMaxResults(5) 28 | ->getQuery(); 29 | 30 | return $query->getResult(); 31 | } 32 | 33 | /** 34 | * @param int $farmId 35 | * 36 | * @return int 37 | */ 38 | public function countByFarm($farmId) 39 | { 40 | $qb = $this->getRepository()->createQueryBuilder('t'); 41 | 42 | $qb->select($qb->expr()->count('t')) 43 | ->where('t.field = '.$farmId); 44 | 45 | $query = $qb->getQuery(); 46 | 47 | return $query->getSingleScalarResult(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tests/AppBundle/Controller/AreaControllerTest.php: -------------------------------------------------------------------------------- 1 | 'testuser', 13 | 'PHP_AUTH_PW' => 'test123' 14 | )); 15 | 16 | $crawler = $client->request('GET', '/areas'); 17 | 18 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/AppBundle/Controller/DashboardControllerTest.php: -------------------------------------------------------------------------------- 1 | 'testuser', 14 | 'PHP_AUTH_PW' => 'test123' 15 | )); 16 | 17 | $container = $client->getContainer(); 18 | $container->get('session')->set('activeFarm', 1); 19 | 20 | $crawler = $client->request('GET', '/'); 21 | 22 | $this->assertEquals(302, $client->getResponse()->getStatusCode()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/AppBundle/Controller/DeviceControllerTest.php: -------------------------------------------------------------------------------- 1 | 'testuser', 13 | 'PHP_AUTH_PW' => 'test123' 14 | )); 15 | 16 | $crawler = $client->request('GET', '/devices'); 17 | 18 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/AppBundle/Controller/FieldControllerTest.php: -------------------------------------------------------------------------------- 1 | 'testuser', 13 | 'PHP_AUTH_PW' => 'test123' 14 | )); 15 | 16 | $crawler = $client->request('GET', '/farms'); 17 | 18 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/AppBundle/Controller/InventoryControllerTest.php: -------------------------------------------------------------------------------- 1 | 'testuser', 13 | 'PHP_AUTH_PW' => 'test123' 14 | )); 15 | 16 | $crawler = $client->request('GET', '/inventories'); 17 | 18 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/AppBundle/Controller/PlantControllerTest.php: -------------------------------------------------------------------------------- 1 | 'testuser', 14 | 'PHP_AUTH_PW' => 'test123' 15 | )); 16 | 17 | $container = $client->getContainer(); 18 | $container->get('session')->set('activeFarm', 1); 19 | 20 | $crawler = $client->request('GET', '/plants'); 21 | 22 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/AppBundle/Controller/ReservoirControllerTest.php: -------------------------------------------------------------------------------- 1 | 'testuser', 13 | 'PHP_AUTH_PW' => 'test123' 14 | )); 15 | 16 | $crawler = $client->request('GET', '/reservoirs'); 17 | 18 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/AppBundle/Controller/TaskControllerTest.php: -------------------------------------------------------------------------------- 1 | 'testuser', 13 | 'PHP_AUTH_PW' => 'test123' 14 | )); 15 | 16 | $crawler = $client->request('GET', '/tasks'); 17 | 18 | $this->assertEquals(200, $client->getResponse()->getStatusCode()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /var/cache/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/var/cache/.gitkeep -------------------------------------------------------------------------------- /var/logs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/var/logs/.gitkeep -------------------------------------------------------------------------------- /var/sessions/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/var/sessions/.gitkeep -------------------------------------------------------------------------------- /web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /web/.htaccess: -------------------------------------------------------------------------------- 1 | # Use the front controller as index file. It serves as a fallback solution when 2 | # every other rewrite/redirect fails (e.g. in an aliased environment without 3 | # mod_rewrite). Additionally, this reduces the matching process for the 4 | # start page (path "/") because otherwise Apache will apply the rewriting rules 5 | # to each configured DirectoryIndex file (e.g. index.php, index.html, index.pl). 6 | DirectoryIndex app.php 7 | 8 | # By default, Apache does not evaluate symbolic links if you did not enable this 9 | # feature in your server configuration. Uncomment the following line if you 10 | # install assets as symlinks or if you experience problems related to symlinks 11 | # when compiling LESS/Sass/CoffeScript assets. 12 | # Options FollowSymlinks 13 | 14 | # Disabling MultiViews prevents unwanted negotiation, e.g. "/app" should not resolve 15 | # to the front controller "/app.php" but be rewritten to "/app.php/app". 16 | 17 | Options -MultiViews 18 | 19 | 20 | 21 | RewriteEngine On 22 | 23 | # Determine the RewriteBase automatically and set it as environment variable. 24 | # If you are using Apache aliases to do mass virtual hosting or installed the 25 | # project in a subdirectory, the base path will be prepended to allow proper 26 | # resolution of the app.php file and to redirect to the correct URI. It will 27 | # work in environments without path prefix as well, providing a safe, one-size 28 | # fits all solution. But as you do not need it in this case, you can comment 29 | # the following 2 lines to eliminate the overhead. 30 | RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$ 31 | RewriteRule ^(.*) - [E=BASE:%1] 32 | 33 | # Sets the HTTP_AUTHORIZATION header removed by Apache 34 | RewriteCond %{HTTP:Authorization} . 35 | RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 36 | 37 | # Redirect to URI without front controller to prevent duplicate content 38 | # (with and without `/app.php`). Only do this redirect on the initial 39 | # rewrite by Apache and not on subsequent cycles. Otherwise we would get an 40 | # endless redirect loop (request -> rewrite to front controller -> 41 | # redirect -> request -> ...). 42 | # So in case you get a "too many redirects" error or you always get redirected 43 | # to the start page because your Apache does not expose the REDIRECT_STATUS 44 | # environment variable, you have 2 choices: 45 | # - disable this feature by commenting the following 2 lines or 46 | # - use Apache >= 2.3.9 and replace all L flags by END flags and remove the 47 | # following RewriteCond (best solution) 48 | RewriteCond %{ENV:REDIRECT_STATUS} ^$ 49 | RewriteRule ^app\.php(?:/(.*)|$) %{ENV:BASE}/$1 [R=301,L] 50 | 51 | # If the requested filename exists, simply serve it. 52 | # We only want to let Apache serve files and not directories. 53 | RewriteCond %{REQUEST_FILENAME} -f 54 | RewriteRule ^ - [L] 55 | 56 | # Rewrite all other queries to the front controller. 57 | RewriteRule ^ %{ENV:BASE}/app.php [L] 58 | 59 | 60 | 61 | 62 | # When mod_rewrite is not available, we instruct a temporary redirect of 63 | # the start page to the front controller explicitly so that the website 64 | # and the generated links can still be used. 65 | RedirectMatch 302 ^/$ /app.php/ 66 | # RedirectTemp cannot be used instead 67 | 68 | 69 | -------------------------------------------------------------------------------- /web/app.php: -------------------------------------------------------------------------------- 1 | handle($request); 19 | $response->send(); 20 | $kernel->terminate($request, $response); 21 | -------------------------------------------------------------------------------- /web/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/apple-touch-icon.png -------------------------------------------------------------------------------- /web/assets/css/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/css/.DS_Store -------------------------------------------------------------------------------- /web/assets/css/material-design-icons/fonts/Material-Design-Iconic-Font.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/css/material-design-icons/fonts/Material-Design-Iconic-Font.eot -------------------------------------------------------------------------------- /web/assets/css/material-design-icons/fonts/Material-Design-Iconic-Font.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/css/material-design-icons/fonts/Material-Design-Iconic-Font.ttf -------------------------------------------------------------------------------- /web/assets/css/material-design-icons/fonts/Material-Design-Iconic-Font.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/css/material-design-icons/fonts/Material-Design-Iconic-Font.woff -------------------------------------------------------------------------------- /web/assets/css/material-design-icons/fonts/Material-Design-Iconic-Font.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/css/material-design-icons/fonts/Material-Design-Iconic-Font.woff2 -------------------------------------------------------------------------------- /web/assets/css/material-design-icons/less/border.less: -------------------------------------------------------------------------------- 1 | // Bordered icons 2 | // ------------------------- 3 | 4 | .@{zmdi-css-prefix}-border { 5 | padding: .1em .25em; 6 | border: solid .1em @md-border-color; 7 | border-radius: 2px; 8 | } 9 | 10 | .@{zmdi-css-prefix}-border-circle { 11 | padding: .1em .25em; 12 | border: solid .1em @md-border-color; 13 | border-radius: 50%; 14 | } 15 | -------------------------------------------------------------------------------- /web/assets/css/material-design-icons/less/core.less: -------------------------------------------------------------------------------- 1 | // Core Class Definition 2 | // ------------------------- 3 | 4 | .@{zmdi-icon-prefix} { 5 | display: inline-block; 6 | font: normal normal normal 14px/1 '@{zmdi-font-name}'; 7 | font-size: inherit; 8 | text-rendering: auto; 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | } 12 | -------------------------------------------------------------------------------- /web/assets/css/material-design-icons/less/fixed-width.less: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | 4 | .@{zmdi-css-prefix}-fw { 5 | width: (18em / 14); 6 | text-align: center; 7 | } -------------------------------------------------------------------------------- /web/assets/css/material-design-icons/less/list.less: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .@{zmdi-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: @zmdi-li-width; 7 | list-style-type: none; 8 | > li { 9 | position: relative; 10 | } 11 | } 12 | .@{zmdi-css-prefix}-li { 13 | position: absolute; 14 | left: -@zmdi-li-width; 15 | width: @zmdi-li-width; 16 | top: (2em / 14); 17 | text-align: center; 18 | &.@{zmdi-css-prefix}-lg { 19 | left: (-@zmdi-li-width + (4em / 14)); 20 | } 21 | } -------------------------------------------------------------------------------- /web/assets/css/material-design-icons/less/material-design-iconic-font.less: -------------------------------------------------------------------------------- 1 | /*! 2 | * Material Design Iconic Font by Sergey Kupletsky (@zavoloklom) - http://zavoloklom.github.io/material-design-iconic-font/ 3 | * License - http://zavoloklom.github.io/material-design-iconic-font/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables.less"; 7 | @import "path.less"; 8 | @import "core.less"; 9 | @import "sizes.less"; 10 | @import "fixed-width.less"; 11 | @import "list.less"; 12 | @import "border.less"; 13 | @import "pulled.less"; 14 | @import "spinned.less"; 15 | @import "rotated.less"; 16 | @import "stacked.less"; 17 | @import "icons.less"; 18 | @import "aliases.less"; -------------------------------------------------------------------------------- /web/assets/css/material-design-icons/less/path.less: -------------------------------------------------------------------------------- 1 | // Font path 2 | // -------------------------- 3 | 4 | @font-face { 5 | font-family: '@{zmdi-font-name}'; 6 | src: 7 | url('@{zmdi-font-path}/Material-Design-Iconic-Font.woff2?v=@{zmdi-version}') format('woff2'), 8 | url('@{zmdi-font-path}/Material-Design-Iconic-Font.woff?v=@{zmdi-version}') format('woff'), 9 | url('@{zmdi-font-path}/Material-Design-Iconic-Font.ttf?v=@{zmdi-version}') format('truetype'); 10 | font-weight: normal; 11 | font-style: normal; 12 | } -------------------------------------------------------------------------------- /web/assets/css/material-design-icons/less/pulled.less: -------------------------------------------------------------------------------- 1 | // Pulled icons 2 | // ------------------------- 3 | 4 | .@{zmdi-icon-prefix} { 5 | &.pull-left { 6 | float: left; 7 | margin-right: .15em; 8 | } 9 | &.pull-right { 10 | float: right; 11 | margin-left: .15em; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /web/assets/css/material-design-icons/less/rotated.less: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped icons 2 | // ------------------------- 3 | 4 | .@{zmdi-css-prefix}-rotate-90 { 5 | transform: rotate(90deg); 6 | } 7 | .@{zmdi-css-prefix}-rotate-180 { 8 | transform: rotate(180deg); 9 | } 10 | .@{zmdi-css-prefix}-rotate-270 { 11 | transform: rotate(270deg); 12 | } 13 | 14 | .@{zmdi-css-prefix}-flip-horizontal { 15 | transform: scale(-1, 1); 16 | } 17 | .@{zmdi-css-prefix}-flip-vertical { 18 | transform: scale(1, -1); 19 | } -------------------------------------------------------------------------------- /web/assets/css/material-design-icons/less/sizes.less: -------------------------------------------------------------------------------- 1 | // Icon sizes 2 | // ------------------------- 3 | 4 | .@{zmdi-css-prefix}-lg { 5 | font-size: (4em / 3); 6 | line-height: (3em / 4); 7 | vertical-align: -15%; 8 | } 9 | .@{zmdi-css-prefix}-2x { 10 | font-size: 2em; 11 | } 12 | .@{zmdi-css-prefix}-3x { 13 | font-size: 3em; 14 | } 15 | .@{zmdi-css-prefix}-4x { 16 | font-size: 4em; 17 | } 18 | .@{zmdi-css-prefix}-5x { 19 | font-size: 5em; 20 | } -------------------------------------------------------------------------------- /web/assets/css/material-design-icons/less/spinned.less: -------------------------------------------------------------------------------- 1 | // Spinning Icons 2 | // -------------------------- 3 | 4 | .@{zmdi-css-prefix}-spin { 5 | animation: zmdi-spin 1.5s infinite linear; 6 | } 7 | 8 | .@{zmdi-css-prefix}-spin-reverse { 9 | animation: zmdi-spin-reverse 1.5s infinite linear; 10 | } 11 | 12 | // Spin 13 | @keyframes zmdi-spin { 14 | 0% { 15 | transform: rotate(0deg); 16 | } 17 | 100% { 18 | transform: rotate(359deg); 19 | } 20 | } 21 | 22 | // Spin Reverse 23 | @keyframes zmdi-spin-reverse { 24 | 0% { 25 | transform: rotate(0deg); 26 | } 27 | 100% { 28 | transform: rotate(-359deg); 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /web/assets/css/material-design-icons/less/stacked.less: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .@{zmdi-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .@{zmdi-css-prefix}-stack-1x, .@{zmdi-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .@{zmdi-css-prefix}-stack-1x { 19 | line-height: inherit; 20 | } 21 | .@{zmdi-css-prefix}-stack-2x { 22 | font-size: 2em; 23 | } 24 | .@{zmdi-css-prefix}-inverse { 25 | color: @zmdi-inverse; 26 | } -------------------------------------------------------------------------------- /web/assets/css/material-design-icons/less/variables.less: -------------------------------------------------------------------------------- 1 | // Variables 2 | // -------------------------- 3 | 4 | @zmdi-font-name: "Material Icons"; 5 | @zmdi-font-path: "../fonts"; 6 | @zmdi-css-prefix: mdi-hc; 7 | @zmdi-icon-prefix: mdi; 8 | @zmdi-version: "2.2.0"; 9 | 10 | @zmdi-border-color: #9E9E9E; 11 | @zmdi-inverse: #FFFFFF; 12 | @zmdi-li-width: (30em / 14); 13 | 14 | // Legacy code for backward capability with 2.0.x version 15 | 16 | @md-font-path: "../fonts"; 17 | @md-css-prefix: md; 18 | @md-icon-prefix: mdi; 19 | @md-version: "2.2.0"; 20 | 21 | @md-border-color: #9E9E9E; 22 | @md-inverse: #FFFFFF; 23 | @md-li-width: (30em / 14); -------------------------------------------------------------------------------- /web/assets/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /web/assets/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /web/assets/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /web/assets/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /web/assets/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/img/favicon.png -------------------------------------------------------------------------------- /web/assets/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/img/logo.png -------------------------------------------------------------------------------- /web/assets/img/plant-basil.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/img/plant-basil.jpg -------------------------------------------------------------------------------- /web/assets/img/tania.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/img/tania.png -------------------------------------------------------------------------------- /web/assets/js/area.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | $(document).ready(function() { 3 | /* form validation here */ 4 | $('#area_name').keyup(function(e) { 5 | var maxLength = 50; 6 | var textlen = $(this).val().length; 7 | 8 | if(textlen <= maxLength) { 9 | var spanText = "Name ("+textlen+"/"+maxLength+" chars)"; 10 | $('#label_area_name').text(spanText); 11 | } 12 | }); 13 | }); 14 | })(); -------------------------------------------------------------------------------- /web/assets/js/dashboard.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | $(document).ready(function() { 3 | var fieldMap = L.map('map'); 4 | var locations = $('#map').data('locations'); 5 | var markers = []; 6 | 7 | L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', { 8 | maxZoom: 18, 9 | attribution: 'Map data © OpenStreetMap contributors, ' + 10 | 'CC-BY-SA, ' + 11 | 'Imagery © Mapbox', 12 | id: 'mapbox.streets' 13 | }).addTo(fieldMap); 14 | 15 | locations.forEach(function(latLng) { 16 | if(latLng[0] !== null || latLng[1] !== null) { 17 | // create the marker 18 | var marker = L.marker(latLng); 19 | markers.push(marker); 20 | } 21 | }); 22 | 23 | var group = new L.featureGroup(markers); 24 | fieldMap.fitBounds(group.getBounds()); 25 | group.addTo(fieldMap); 26 | }); 27 | })(); -------------------------------------------------------------------------------- /web/assets/js/field-map-show.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | $(document).ready(function() { 3 | var fieldMap, markerLayer; 4 | var currentLatLng = [$('#map').data('lat'), $('#map').data('lng')]; 5 | var defaultLatLng = [-8.4960936, 115.2485298]; 6 | 7 | /* Initialize the map and tile layer */ 8 | function mapInit(latLng) { 9 | fieldMap = L.map('map').setView(latLng, 13); 10 | markerLayer = L.marker(latLng).addTo(fieldMap); 11 | 12 | L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', { 13 | maxZoom: 18, 14 | attribution: 'Map data © OpenStreetMap contributors, ' + 15 | 'CC-BY-SA, ' + 16 | 'Imagery © Mapbox', 17 | id: 'mapbox.streets' 18 | }).addTo(fieldMap); 19 | } 20 | 21 | /* Get current lat and lng from the click on top of map */ 22 | function onMapClick(e) { 23 | fieldMap.removeLayer(markerLayer); 24 | 25 | $('#field_lat').val(e.latlng.lat); 26 | $('#field_lng').val(e.latlng.lng); 27 | 28 | markerLayer = L.marker([e.latlng.lat, e.latlng.lng]).addTo(fieldMap); 29 | } 30 | 31 | if(currentLatLng[0] === "" || currentLatLng[1] === "") { 32 | if("geolocation" in navigator){ 33 | navigator.geolocation.getCurrentPosition(function(position){ 34 | mapInit([position.coords.latitude, position.coords.longitude]); 35 | fieldMap.on('click', onMapClick); 36 | }, function(error) { 37 | // if error it will use default lat lng 38 | mapInit(defaultLatLng); 39 | fieldMap.on('click', onMapClick); 40 | }); 41 | } else { 42 | mapInit(defaultLatLng); 43 | fieldMap.on('click', onMapClick); 44 | } 45 | } else { 46 | mapInit(currentLatLng); 47 | fieldMap.on('click', onMapClick); 48 | } 49 | 50 | /* form validation here */ 51 | $('#field_name').keyup(function(e) { 52 | var maxLength = 50; 53 | var textlen = $(this).val().length; 54 | 55 | if(textlen <= maxLength) { 56 | var spanText = "Name ("+textlen+"/"+maxLength+" chars)"; 57 | $('#label_field_name').text(spanText); 58 | } 59 | }); 60 | }); 61 | })(); -------------------------------------------------------------------------------- /web/assets/js/field-map.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | $(document).ready(function() { 3 | var fieldMap, markerLayer; 4 | var defaultLatLng = [-8.4960936, 115.2485298]; 5 | 6 | /* Initialize the map and tile layer */ 7 | function mapInit(latLng) { 8 | fieldMap = L.map('map').setView(latLng, 13); 9 | markerLayer = L.marker(latLng).addTo(fieldMap); 10 | 11 | L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', { 12 | maxZoom: 18, 13 | attribution: 'Map data © OpenStreetMap contributors, ' + 14 | 'CC-BY-SA, ' + 15 | 'Imagery © Mapbox', 16 | id: 'mapbox.streets' 17 | }).addTo(fieldMap); 18 | } 19 | 20 | /* Get current lat and lng from the click on top of map */ 21 | function onMapClick(e) { 22 | fieldMap.removeLayer(markerLayer); 23 | 24 | $('#field_lat').val(e.latlng.lat); 25 | $('#field_lng').val(e.latlng.lng); 26 | 27 | markerLayer = L.marker([e.latlng.lat, e.latlng.lng]).addTo(fieldMap); 28 | } 29 | 30 | if("geolocation" in navigator){ 31 | navigator.geolocation.getCurrentPosition(function(position){ 32 | mapInit([position.coords.latitude, position.coords.longitude]); 33 | fieldMap.on('click', onMapClick); 34 | 35 | // Automatically fill the lat lng input fields 36 | $('#field_lat').val(position.coords.latitude); 37 | $('#field_lng').val(position.coords.longitude); 38 | }, function(error) { 39 | // if error it will use default lat lng 40 | mapInit(defaultLatLng); 41 | fieldMap.on('click', onMapClick); 42 | 43 | // Automatically fill the lat lng input fields 44 | $('#field_lat').val(position.coords.latitude); 45 | $('#field_lng').val(position.coords.longitude); 46 | }); 47 | } else { 48 | mapInit(defaultLatLng); 49 | fieldMap.on('click', onMapClick); 50 | 51 | // Automatically fill the lat lng input fields 52 | $('#field_lat').val(position.coords.latitude); 53 | $('#field_lng').val(position.coords.longitude); 54 | } 55 | 56 | /* form validation here */ 57 | $('#field_name').keyup(function(e) { 58 | var maxLength = 50; 59 | var textlen = $(this).val().length; 60 | 61 | if(textlen <= maxLength) { 62 | var spanText = "Name ("+textlen+"/"+maxLength+" chars)"; 63 | $('#label_field_name').text(spanText); 64 | } 65 | }); 66 | }); 67 | })(); -------------------------------------------------------------------------------- /web/assets/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /web/assets/js/plant.js: -------------------------------------------------------------------------------- 1 | jQuery.datetimepicker.setLocale(global.locale); 2 | $(".date-picker").datetimepicker({ 3 | format: 'Y-m-d', 4 | timepicker: false 5 | }); -------------------------------------------------------------------------------- /web/assets/js/task.js: -------------------------------------------------------------------------------- 1 | jQuery.datetimepicker.setLocale(global.locale); 2 | $(".date-time-picker").datetimepicker({ 3 | format: 'Y-m-d H:i' 4 | }); 5 | -------------------------------------------------------------------------------- /web/assets/lib/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/.DS_Store -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-Black.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-Black.eot -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-Black.ttf -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-Black.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-Black.woff -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-Black.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-Black.woff2 -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-BlackItalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-BlackItalic.eot -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-BlackItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-BlackItalic.ttf -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-BlackItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-BlackItalic.woff -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-BlackItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-BlackItalic.woff2 -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-Bold.eot -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-Bold.ttf -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-Bold.woff -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-Bold.woff2 -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-BoldItalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-BoldItalic.eot -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-BoldItalic.ttf -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-BoldItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-BoldItalic.woff -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-BoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-BoldItalic.woff2 -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-Light.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-Light.eot -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-Light.ttf -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-Light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-Light.woff -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-Light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-Light.woff2 -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-LightItalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-LightItalic.eot -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-LightItalic.ttf -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-LightItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-LightItalic.woff -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-LightItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-LightItalic.woff2 -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-Medium.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-Medium.eot -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-Medium.ttf -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-Medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-Medium.woff -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-Medium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-Medium.woff2 -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-MediumItalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-MediumItalic.eot -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-MediumItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-MediumItalic.ttf -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-MediumItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-MediumItalic.woff -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-MediumItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-MediumItalic.woff2 -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-Regular.eot -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-Regular.ttf -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-Regular.woff -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-Regular.woff2 -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-RegularItalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-RegularItalic.eot -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-RegularItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-RegularItalic.ttf -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-RegularItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-RegularItalic.woff -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-RegularItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-RegularItalic.woff2 -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-Thin.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-Thin.eot -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-Thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-Thin.ttf -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-Thin.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-Thin.woff -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-Thin.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-Thin.woff2 -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-ThinItalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-ThinItalic.eot -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-ThinItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-ThinItalic.ttf -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-ThinItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-ThinItalic.woff -------------------------------------------------------------------------------- /web/assets/lib/roboto/Roboto-ThinItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/assets/lib/roboto/Roboto-ThinItalic.woff2 -------------------------------------------------------------------------------- /web/debug.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/debug.html -------------------------------------------------------------------------------- /web/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/favicon.ico -------------------------------------------------------------------------------- /web/robots.txt: -------------------------------------------------------------------------------- 1 | # www.robotstxt.org/ 2 | # www.google.com/support/webmasters/bin/answer.py?hl=en&answer=156449 3 | 4 | User-agent: * 5 | Disallow: 6 | -------------------------------------------------------------------------------- /web/uploads/areas/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/uploads/areas/index.html -------------------------------------------------------------------------------- /web/uploads/fields/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/uploads/fields/index.html -------------------------------------------------------------------------------- /web/uploads/seeds/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/usetania/tania/c682c132cbec91da56df9ff0958060f504ee6381/web/uploads/seeds/index.html --------------------------------------------------------------------------------