diff --git a/.editorconfig b/.editorconfig index c48b9159..d014440d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,5 +7,4 @@ indent_style = space indent_size = 4 [{package.json,.travis.yml}] -indent_style = space indent_size = 2 diff --git a/.env b/.env deleted file mode 100644 index d38b7b00..00000000 --- a/.env +++ /dev/null @@ -1,19 +0,0 @@ -DB_USERNAME=easyapp -DB_NAME=easyapp - -# before deploying to production change to harder password, and don't commit it to git -DB_PASSWORD=veryhardpassword - -# change to your installation address -APP_URL=localhost -APP_HOST=0.0.0.0 -APP_PORT=80 - -# email settings - set to 'smtp' and provide SMTP settings if you want to send emails -EMAIL_PROTOCOL=mail -SMTP_HOST=smtp.gmail.com -SMTP_USER=user -SMTP_PASS=password -SMTP_CRYPTO=ssl -SMTP_PORT=25 - diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..176a458f --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..cb58ca69 --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,58 @@ +# Code of Conduct + +### Our Pledge + +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. + +### Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language. +* Being respectful of differing viewpoints and experiences. +* Gracefully accepting constructive criticism. +* Focusing on what is best for the community. +* Showing empathy towards other community members. + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances. +* Trolling, insulting/derogatory comments, and personal or political attacks. +* Public or private harassment. +* Publishing others' private information, such as a physical or electronic address, without explicit permission. +* Other conduct which could reasonably be considered inappropriate in a professional setting. + +### Our Responsibilities + +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. + +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. + +### Scope + +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. + +### Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project owner at +[alextselegidis@gmail.com](alextselegidis@gmail.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 owner is obligated to maintain +confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be +posted separately. + +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. + +### Attribution + +This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.4, +available at http://contributor-covenant.org/version/1/4. diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 00000000..f1baecf0 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,17 @@ +# Contributing + +When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other +method with the owner of this repository before making a change. + +Please note we have a code of conduct, please follow it in all your interactions with the project. + +## Pull Request Process + +1. Ensure any install or build dependencies are removed before the end of the layer when doing a build. +2. Ensure that your changes comply with the project's coding guidelines and that it's sufficiently documented. +3. Update the README.md with details of changes to the interface, this includes new environment variables, exposed + ports, useful file locations and container parameters. +4. Target the develop branch for your Pull Requests as this is were new changes are introduced. +4. After being successfully reviewed pull requests will be merged to develop branch and will finally be included in an + upcoming release. + diff --git a/.gitignore b/.gitignore index a55b9963..e0de0c53 100644 --- a/.gitignore +++ b/.gitignore @@ -1,21 +1,28 @@ /*.zip /.idea/ /.tmp-package/ -/doc/apigen/ -/doc/jsdoc/ -/doc/plato/ +/build/ +/docs/apigen/html +/docs/jsdoc/html +/docs/plato/html +/docker/mysql/* +!/docker/mysql/.gitkeep /node_modules/ /npm-debug.log -/src/config.php -/src/storage/cache/* -!/src/storage/cache/.htaccess -!/src/storage/cache/index.html -/src/storage/logs/* -!/src/storage/logs/.htaccess -!/src/storage/logs/index.html -/src/storage/sessions/* -!/src/storage/sessions/.htaccess -!/src/storage/sessions/index.html -/src/storage/uploads/* -/!src/storage/uploads/index.html +/assets/js/**/*.min.js +/assets/css/**/*.min.css +/config.php +/storage/cache/* +!/storage/cache/.htaccess +!/storage/cache/index.html +/storage/logs/* +!/storage/logs/.htaccess +!/storage/logs/index.html +/storage/sessions/* +!/storage/sessions/.htaccess +!/storage/sessions/index.html +/storage/uploads/* +/!storage/uploads/index.html /vendor/ +/metafile +.DS_Store diff --git a/CHANGELOG.md b/CHANGELOG.md index 18f56fe2..1a66ca83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,9 +6,9 @@ developers to maintain and readjust their custom modifications on the main proje The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [1.3.2] +## [1.3.2] - 2018-07-29 -## Fixed +### Fixed - #480: Make the app GDPR - new EU privacy regulations compliant. - #485: Make REST API search check with "q" parameter case insensitive. @@ -17,7 +17,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - #510: Providers should not be able to create appointments for other providers in the backend calendar page. - #512: Only show appointments of the currently logged in provider. -## [1.3.1] +## [1.3.1] - 2018-06-03 ### Added @@ -25,11 +25,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - #441: Added time format selection - #452: Provide more information when errors occur during the installation. -## Changed +### Changed - #494: French translation corrections/improvements. -## Fixed +### Fixed - #433: Selected date when editing an appointment - #436: All days unavailable in agendaDay view @@ -45,7 +45,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - #495: Database migration fixes (from 1.2.1 to 1.3.x). - #497: Backend settings are not being displayed on page load when the user is not an admin. -## [1.3.0] +## [1.3.0] - 2018-02-28 ### Added diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 9cdfc159..00000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,75 +0,0 @@ -# Contributing - -When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other -method with the owner of this repository before making a change. - -Please note we have a code of conduct, please follow it in all your interactions with the project. - -## Pull Request Process - -1. Ensure any install or build dependencies are removed before the end of the layer when doing a build. -2. Ensure that your changes comply with the project's coding guidelines and that it's sufficiently documented. -3. Update the README.md with details of changes to the interface, this includes new environment variables, exposed - ports, useful file locations and container parameters. -4. Target the develop branch for your Pull Requests as this is were new changes are introduced. -4. After being successfully reviewed pull requests will be merged to develop branch and will finally be included in an - upcoming release. - -## Code of Conduct - -### Our Pledge - -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. - -### Our Standards - -Examples of behavior that contributes to creating a positive environment include: - -* Using welcoming and inclusive language. -* Being respectful of differing viewpoints and experiences. -* Gracefully accepting constructive criticism. -* Focusing on what is best for the community. -* Showing empathy towards other community members. - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery and unwelcome sexual attention or advances. -* Trolling, insulting/derogatory comments, and personal or political attacks. -* Public or private harassment. -* Publishing others' private information, such as a physical or electronic address, without explicit permission. -* Other conduct which could reasonably be considered inappropriate in a professional setting. - -### Our Responsibilities - -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. - -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. - -### Scope - -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. - -### Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project owner at -[alextselegidis@gmail.com](alextselegidis@gmail.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 owner is obligated to maintain -confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be -posted separately. - -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. - -### Attribution - -This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.4, -available at http://contributor-covenant.org/version/1/4. diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index fd721d9e..00000000 --- a/Dockerfile +++ /dev/null @@ -1,16 +0,0 @@ -FROM php:7.0-apache - -ENV PROJECT_DIR=/var/www/html \ - APP_URL=localhost - -RUN docker-php-ext-install mysqli gettext - -COPY ./src $PROJECT_DIR -COPY docker-entrypoint.sh /entrypoint.sh - -RUN sed -i 's/\r//' /entrypoint.sh - -VOLUME $PROJECT_DIR/storage - -ENTRYPOINT ["/bin/bash", "/entrypoint.sh"] -CMD ["run"] diff --git a/README.md b/README.md index b3851f03..e028d322 100644 --- a/README.md +++ b/README.md @@ -1,79 +1,108 @@ -Easy!Appointments -================ +

+
+ + Easy!Appointments + +
+ Easy!Appointments +
+

- +
-### Organize your business! Exploit human resources that can be used in other tasks more efficiently. +

+ A powerful Open Source Web Scheduler that can be installed on your server. +

-**Easy!Appointments** is a highly customizable web application that allows your customers to book -appointments with you via the web. Moreover, it provides the ability to sync your data with -Google Calendar so you can use them with other services. It is an open source project and you -can download and install it **even for commercial use**. Easy!Appointments will run smoothly with -your existing website, because it can be installed in a single folder of the server and of course, -both sites can share the same database. +

+ GitHub + GitHub release (latest by date) + GitHub All Releases +

-### Features +

+ About • + Features • + Setup • + Installation • + License +

-The project was designed to be flexible and reliable so as to be able to meet the needs of any -kind of enterprise. You can read the main features of the system below: +![screenshot](screenshot.png) -* Full customers and appointments management. -* Services and service providers organization. -* Workflow and booking rules. +## About + +**Easy!Appointments** is a highly customizable web application that allows customers to book appointments with you +via a sophisticated web interface. Moreover, it provides the ability to sync your data with Google Calendar so you can +use them with other services. It is an open source project that you can download and install **even for commercial use**. +Easy!Appointments will run smoothly with your existing website as it can be installed in a single folder of the +server and of course share an existing database. + +## Features + +The application is designed to be flexible enough so that it can handle any enterprise work flow. + +* Customers and appointments management. +* Services and providers organization. +* Working plan and booking rules. * Google Calendar synchronization. * Email notifications system. -* Standalone installation (like WordPress, Drupal, Joomla and other web systems). +* Self hosted installation. * Translated user interface. -* User community support. +* User community support. -### Installation +## Setup -Since Easy!Appointments is a web application, it runs on a web server and thus you will need to -perform the following steps in order to install the system on your server: +To clone and run this application, you'll need [Git](https://git-scm.com), [Node.js](https://nodejs.org/en/download/) (which comes with [npm](http://npmjs.com)) and [Composer](https://getcomposer.org) installed on your computer. From your command line: + +```bash +# Clone this repository +$ git clone https://github.com/alextselegidis/easyappointments.git + +# Go into the repository +$ cd easyappointments + +# Install dependencies +$ npm install && composer install + +# Start the file watcher +$ npm start +``` + +Note: If you're using Linux Bash for Windows, [see this guide](https://www.howtogeek.com/261575/how-to-run-graphical-linux-desktop-applications-from-windows-10s-bash-shell/) or use `node` from the command prompt. + +You can build the files by running `npm run build`. This command will bundle everything to a `build` directory. + +## Installation + +You will need to perform the following steps to install the application on your server: * Make sure that your server has Apache/Nginx, PHP and MySQL installed. -* Create a new database (or use an existing). +* Create a new database (or use an existing one). * Copy the "easyappointments" source folder on your server. * Make sure that the "storage" directory is writable. -* Rename the "config-sample.php" file to "config.php" and set your server properties. -* Open your browser on the Easy!Appointments URL and follow the installation guide. -* That's it! You can now use Easy!Appointments at your will. +* Rename the "config-sample.php" file to "config.php" and update its contents based on your environment. +* Open the browser on the Easy!Appointments URL and follow the installation guide. -You will find the latest release at [easyappointments.org](http://easyappointments.org). -If you have problems installing or configuring the application take a look on the -[wiki pages](https://github.com/alextselegidis/easyappointments/wiki) or visit the +That's it! You can now use Easy!Appointments at your will. + +You will find the latest release at [easyappointments.org](https://easyappointments.org). +If you have problems installing or configuring the application visit the [official support group](https://groups.google.com/forum/#!forum/easy-appointments). You can also report problems on the [issues page](https://github.com/alextselegidis/easyappointments/issues) and help the development progress. -### Docker -To start Easy!Appointments using Docker in development configuration, with source files mounted into container, run: -``` -docker-compose up -``` +## License -Production deployment can be made by changing required values in .env file (DB_PASSWORD, APP_URL, APP_PORT) and running: -``` -docker-compose -f docker-compose.prod.yml up -d -``` +Code Licensed Under [GPL v3.0](https://www.gnu.org/licenses/gpl-3.0.en.html) | Content Under [CC BY 3.0](https://creativecommons.org/licenses/by/3.0/) -Database data will be stored in named volume `easyappointments_easy-appointments-data`, and app storage (logs, cache, uploads) in `easyappointments_easy-appointments-storage`. -To find where exactly they are stored, you can run -``` -docker volume inspect easyappointments_easy-appointments-storage -``` +--- -Production containers will automatically be restarted in case of crash / server reboot. For more info, take a look into `docker-compose.prod.yml` file. +Website [alextselegidis.com](https://alextselegidis.com)  ·  +GitHub [alextselegidis](https://github.com/alextselegidis)  ·  +Twitter [@alextselegidis](https://twitter.com/AlexTselegidis) -### User Feedback - -Whether it is new ideas or defects, your feedback is highly appreciated and will be taken into -consideration for the following releases of the project. Share your experience and discuss your -thoughts with other users through communities. Create issues with suggestions on new features or -bug reports. - -### Translate Easy!Appointments - -As of version 1.0 Easy!Appointments supports translated user interface. If you want to contribute to the -translation process read the [get involved](https://github.com/alextselegidis/easyappointments/blob/master/doc/get-involved.md) -page for additional information. +###### More Projects On Github +###### ⇾ [Plainpad · Self Hosted Note Taking App](https://github.com/alextselegidis/plainpad) +###### ⇾ [Questionful · Web Questionnaires Made Easy](https://github.com/alextselegidis/questionful) +###### ⇾ [Integravy · Service Orchestration At Your Fingertips](https://github.com/alextselegidis/integravy) diff --git a/src/application/.htaccess b/application/.htaccess similarity index 100% rename from src/application/.htaccess rename to application/.htaccess diff --git a/application/config/autoload.php b/application/config/autoload.php new file mode 100644 index 00000000..1d600e7d --- /dev/null +++ b/application/config/autoload.php @@ -0,0 +1,117 @@ + 'arabic', + 'bu' => 'bulgarian', + 'zh' => 'chinese', + 'da' => 'danish', + 'nl' => 'dutch', + 'en' => 'english', + 'fi' => 'finnish', + 'fr' => 'french', + 'de' => 'german', + 'el' => 'greek', + 'hi' => 'hindi', + 'hu' => 'hungarian', + 'it' => 'italian', + 'ja' => 'japanese', + 'pl' => 'polish', + 'pt' => 'portuguese', + 'ro' => 'romanian', + 'ru' => 'russian', + 'sk' => 'slovak', + 'es' => 'spanish', + 'tr' => 'turkish', + 'sv' => 'swedish' + ][substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2)] + : Config::LANGUAGE; + +/* +|-------------------------------------------------------------------------- +| Available Languages +|-------------------------------------------------------------------------- +| +| Each item of this array must be a directory with the translation files in +| the /application/language directory. The users will be able to select one +| of these languages. +| +*/ +$config['available_languages'] = [ + 'arabic', + 'bulgarian', + 'catalan', + 'chinese', + 'czech', + 'danish', + 'dutch', + 'english', + 'finnish', + 'french', + 'german', + 'greek', + 'hindi', + 'hungarian', + 'italian', + 'japanese', + 'marathi', + 'luxembourgish', + 'polish', + 'portuguese', + 'portuguese-br', + 'romanian', + 'russian', + 'slovak', + 'spanish', + 'turkish' +]; + +/* +|-------------------------------------------------------------------------- +| Default Character Set +|-------------------------------------------------------------------------- +| +| This determines which character set is used by default in various methods +| that require a character set to be provided. +| +*/ +$config['charset'] = 'UTF-8'; + +/* +|-------------------------------------------------------------------------- +| Enable/Disable System Hooks +|-------------------------------------------------------------------------- +| +| If you would like to use the 'hooks' feature you must enable it by +| setting this variable to TRUE (boolean). See the user guide for details. +| +*/ +$config['enable_hooks'] = TRUE; + + +/* +|-------------------------------------------------------------------------- +| Class Extension Prefix +|-------------------------------------------------------------------------- +| +| This item allows you to set the filename/classname prefix when extending +| native libraries. For more information please see the user guide: +| +| http://codeigniter.com/user_guide/general/core_classes.html +| http://codeigniter.com/user_guide/general/creating_libraries.html +| +*/ +$config['subclass_prefix'] = 'MY_'; + + +/* +|-------------------------------------------------------------------------- +| Allowed URL Characters +|-------------------------------------------------------------------------- +| +| This lets you specify with a regular expression which characters are permitted +| within your URLs. When someone tries to submit a URL with disallowed +| characters they will get a warning message. +| +| As a security measure you are STRONGLY encouraged to restrict URLs to +| as few characters as possible. By default only these are allowed: a-z 0-9~%.:_- +| +| Leave blank to allow all characters -- but only if you are insane. +| +| DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!! +| +*/ +$config['permitted_uri_chars'] = 'a-z 0-9~%.:_\-'; + + +/* +|-------------------------------------------------------------------------- +| Enable Query Strings +|-------------------------------------------------------------------------- +| +| By default CodeIgniter uses search-engine friendly segment based URLs: +| example.com/who/what/where/ +| +| By default CodeIgniter enables access to the $_GET array. If for some +| reason you would like to disable it, set 'allow_get_array' to FALSE. +| +| You can optionally enable standard query string based URLs: +| example.com?who=me&what=something&where=here +| +| Options are: TRUE or FALSE (boolean) +| +| The other items let you set the query string 'words' that will +| invoke your controllers and its functions: +| example.com/index.php?c=controller&m=function +| +| Please note that some of the helpers won't work as expected when +| this feature is enabled, since CodeIgniter is designed primarily to +| use segment based URLs. +| +*/ +$config['allow_get_array'] = TRUE; +$config['enable_query_strings'] = FALSE; +$config['controller_trigger'] = 'c'; +$config['function_trigger'] = 'm'; +$config['directory_trigger'] = 'd'; // experimental not currently in use + +/* +|-------------------------------------------------------------------------- +| Error Logging Threshold +|-------------------------------------------------------------------------- +| +| If you have enabled error logging, you can set an error threshold to +| determine what gets logged. Threshold options are: +| You can enable error logging by setting a threshold over zero. The +| threshold determines what gets logged. Threshold options are: +| +| 0 = Disables logging, Error logging TURNED OFF +| 1 = Error Messages (including PHP errors) +| 2 = Debug Messages +| 3 = Informational Messages +| 4 = All Messages +| +| For a live site you'll usually only enable Errors (1) to be logged otherwise +| your log files will fill up very fast. +| +*/ +$config['log_threshold'] = 1; + +/* +|-------------------------------------------------------------------------- +| Error Logging Directory Path +|-------------------------------------------------------------------------- +| +| Leave this BLANK unless you would like to set something other than the default +| application/logs/ folder. Use a full server path with trailing slash. +| +*/ +$config['log_path'] = __DIR__ . '/../../storage/logs/'; + +/* +|-------------------------------------------------------------------------- +| Date Format for Logs +|-------------------------------------------------------------------------- +| +| Each item that is logged has an associated date. You can use PHP date +| codes to set your own date formatting +| +*/ +$config['log_date_format'] = 'Y-m-d H:i:s'; + +/* +|-------------------------------------------------------------------------- +| Cache Directory Path +|-------------------------------------------------------------------------- +| +| Leave this BLANK unless you would like to set something other than the default +| system/cache/ folder. Use a full server path with trailing slash. +| +*/ +$config['cache_path'] = __DIR__ . '/../../storage/cache/'; + +/* +|-------------------------------------------------------------------------- +| Cache Busting Token +|-------------------------------------------------------------------------- +| +| This token will be appending to asset URLs in order to invalidate the browser +| cache and enforce end clients to fetch new files. Update the token with each +| new release. +| +*/ +$config['cache_busting_token'] = '93GX4'; + +/* +|-------------------------------------------------------------------------- +| Encryption Key +|-------------------------------------------------------------------------- +| +| If you use the Encryption class or the Session class you +| MUST set an encryption key. See the user guide for info. +| +*/ +$config['encryption_key'] = Config::BASE_URL; + +/* +|-------------------------------------------------------------------------- +| Session Variables +|-------------------------------------------------------------------------- +| +| 'sess_cookie_name' = the name you want for the cookie +| 'sess_expiration' = the number of SECONDS you want the session to last. +| by default sessions last 7200 seconds (two hours). Set to zero for no expiration. +| 'sess_expire_on_close' = Whether to cause the session to expire automatically +| when the browser window is closed +| 'sess_encrypt_cookie' = Whether to encrypt the cookie +| 'sess_use_database' = Whether to save the session data to a database +| 'sess_table_name' = The name of the session database table +| 'sess_match_ip' = Whether to match the user's IP address when reading the session data +| 'sess_match_useragent' = Whether to match the User Agent when reading the session data +| 'sess_time_to_update' = how many seconds between CI refreshing Session Information +| +*/ +$config['sess_driver'] = 'files'; +$config['sess_cookie_name'] = 'ea_session'; +$config['sess_expiration'] = 7200; +$config['sess_save_path'] = __DIR__ . '/../../storage/sessions'; +$config['sess_match_ip'] = FALSE; +$config['sess_time_to_update'] = 300; +$config['sess_regenerate_destroy'] = FALSE; + +/* +|-------------------------------------------------------------------------- +| Cookie Related Variables +|-------------------------------------------------------------------------- +| +| 'cookie_prefix' = Set a prefix if you need to avoid collisions +| 'cookie_domain' = Set to .your-domain.com for site-wide cookies +| 'cookie_path' = Typically will be a forward slash +| 'cookie_secure' = Cookies will only be set if a secure HTTPS connection exists. +| +*/ +$config['cookie_prefix'] = ""; +$config['cookie_domain'] = ""; +$config['cookie_path'] = "/"; +$config['cookie_secure'] = FALSE; + +/* +|-------------------------------------------------------------------------- +| Global XSS Filtering +|-------------------------------------------------------------------------- +| +| Determines whether the XSS filter is always active when GET, POST or +| COOKIE data is encountered +| +*/ +$config['global_xss_filtering'] = TRUE; + +/* +|-------------------------------------------------------------------------- +| Cross Site Request Forgery +|-------------------------------------------------------------------------- +| Enables a CSRF cookie token to be set. When set to TRUE, token will be +| checked on a submitted form. If you are accepting user data, it is strongly +| recommended CSRF protection be enabled. +| +| 'csrf_token_name' = The token name +| 'csrf_cookie_name' = The cookie name +| 'csrf_expire' = The number in seconds the token should expire. +*/ +$config['csrf_protection'] = TRUE; +$config['csrf_token_name'] = 'csrfToken'; +$config['csrf_cookie_name'] = 'csrfCookie'; +$config['csrf_expire'] = 7200; +$config['csrf_exclude_uris'] = ['api/v1/.*']; + +/* +|-------------------------------------------------------------------------- +| Output Compression +|-------------------------------------------------------------------------- +| +| Enables Gzip output compression for faster page loads. When enabled, +| the output class will test whether your server supports Gzip. +| Even if it does, however, not all browsers support compression +| so enable only if you are reasonably sure your visitors can handle it. +| +| VERY IMPORTANT: If you are getting a blank page when compression is enabled it +| means you are prematurely outputting something to your browser. It could +| even be a line of whitespace at the end of one of your scripts. For +| compression to work, nothing can be sent before the output buffer is called +| by the output class. Do not 'echo' any values with compression enabled. +| +*/ +$config['compress_output'] = FALSE; + +/* +|-------------------------------------------------------------------------- +| Master Time Reference +|-------------------------------------------------------------------------- +| +| Options are 'local' or 'gmt'. This pref tells the system whether to use +| your server's local time as the master 'now' reference, or convert it to +| GMT. See the 'date helper' page of the user guide for information +| regarding date handling. +| +*/ +$config['time_reference'] = 'local'; + + +/* +|-------------------------------------------------------------------------- +| Rewrite PHP Short Tags +|-------------------------------------------------------------------------- +| +| If your PHP installation does not have short tag support enabled CI +| can rewrite the tags on-the-fly, enabling you to utilize that syntax +| in your view files. Options are TRUE or FALSE (boolean) +| +*/ +$config['rewrite_short_tags'] = FALSE; + + +/* +|-------------------------------------------------------------------------- +| Reverse Proxy IPs +|-------------------------------------------------------------------------- +| +| If your server is behind a reverse proxy, you must whitelist the proxy IP +| addresses from which CodeIgniter should trust the HTTP_X_FORWARDED_FOR +| header in order to properly identify the visitor's IP address. +| Comma-delimited, e.g. '10.0.1.200,10.0.1.201' +| +*/ +$config['proxy_ips'] = ''; + + +/* End of file config.php */ +/* Location: ./application/config/config.php */ diff --git a/application/config/constants.php b/application/config/constants.php new file mode 100644 index 00000000..6e42bd86 --- /dev/null +++ b/application/config/constants.php @@ -0,0 +1,93 @@ +migration->latest() this is the version that schema will +| be upgraded / downgraded to. +| +*/ +$config['migration_version'] = 20; + + +/* +|-------------------------------------------------------------------------- +| Migrations Path +|-------------------------------------------------------------------------- +| +| Path to your migrations folder. +| Typically, it will be within your application path. +| Also, writing permission is required within the migrations path. +| +*/ +$config['migration_path'] = APPPATH . 'migrations/'; + + +/* End of file migration.php */ +/* Location: ./application/config/migration.php */ diff --git a/application/config/mimes.php b/application/config/mimes.php new file mode 100644 index 00000000..0ec9db0a --- /dev/null +++ b/application/config/mimes.php @@ -0,0 +1,184 @@ + array('application/mac-binhex40', 'application/mac-binhex', 'application/x-binhex40', 'application/x-mac-binhex40'), + 'cpt' => 'application/mac-compactpro', + 'csv' => array('text/x-comma-separated-values', 'text/comma-separated-values', 'application/octet-stream', 'application/vnd.ms-excel', 'application/x-csv', 'text/x-csv', 'text/csv', 'application/csv', 'application/excel', 'application/vnd.msexcel', 'text/plain'), + 'bin' => array('application/macbinary', 'application/mac-binary', 'application/octet-stream', 'application/x-binary', 'application/x-macbinary'), + 'dms' => 'application/octet-stream', + 'lha' => 'application/octet-stream', + 'lzh' => 'application/octet-stream', + 'exe' => array('application/octet-stream', 'application/x-msdownload'), + 'class' => 'application/octet-stream', + 'psd' => array('application/x-photoshop', 'image/vnd.adobe.photoshop'), + 'so' => 'application/octet-stream', + 'sea' => 'application/octet-stream', + 'dll' => 'application/octet-stream', + 'oda' => 'application/oda', + 'pdf' => array('application/pdf', 'application/force-download', 'application/x-download', 'binary/octet-stream'), + 'ai' => array('application/pdf', 'application/postscript'), + 'eps' => 'application/postscript', + 'ps' => 'application/postscript', + 'smi' => 'application/smil', + 'smil' => 'application/smil', + 'mif' => 'application/vnd.mif', + 'xls' => array('application/vnd.ms-excel', 'application/msexcel', 'application/x-msexcel', 'application/x-ms-excel', 'application/x-excel', 'application/x-dos_ms_excel', 'application/xls', 'application/x-xls', 'application/excel', 'application/download', 'application/vnd.ms-office', 'application/msword'), + 'ppt' => array('application/powerpoint', 'application/vnd.ms-powerpoint', 'application/vnd.ms-office', 'application/msword'), + 'pptx' => array('application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/x-zip', 'application/zip'), + 'wbxml' => 'application/wbxml', + 'wmlc' => 'application/wmlc', + 'dcr' => 'application/x-director', + 'dir' => 'application/x-director', + 'dxr' => 'application/x-director', + 'dvi' => 'application/x-dvi', + 'gtar' => 'application/x-gtar', + 'gz' => 'application/x-gzip', + 'gzip' => 'application/x-gzip', + 'php' => array('application/x-httpd-php', 'application/php', 'application/x-php', 'text/php', 'text/x-php', 'application/x-httpd-php-source'), + 'php4' => 'application/x-httpd-php', + 'php3' => 'application/x-httpd-php', + 'phtml' => 'application/x-httpd-php', + 'phps' => 'application/x-httpd-php-source', + 'js' => array('application/x-javascript', 'text/plain'), + 'swf' => 'application/x-shockwave-flash', + 'sit' => 'application/x-stuffit', + 'tar' => 'application/x-tar', + 'tgz' => array('application/x-tar', 'application/x-gzip-compressed'), + 'z' => 'application/x-compress', + 'xhtml' => 'application/xhtml+xml', + 'xht' => 'application/xhtml+xml', + 'zip' => array('application/x-zip', 'application/zip', 'application/x-zip-compressed', 'application/s-compressed', 'multipart/x-zip'), + 'rar' => array('application/x-rar', 'application/rar', 'application/x-rar-compressed'), + 'mid' => 'audio/midi', + 'midi' => 'audio/midi', + 'mpga' => 'audio/mpeg', + 'mp2' => 'audio/mpeg', + 'mp3' => array('audio/mpeg', 'audio/mpg', 'audio/mpeg3', 'audio/mp3'), + 'aif' => array('audio/x-aiff', 'audio/aiff'), + 'aiff' => array('audio/x-aiff', 'audio/aiff'), + 'aifc' => 'audio/x-aiff', + 'ram' => 'audio/x-pn-realaudio', + 'rm' => 'audio/x-pn-realaudio', + 'rpm' => 'audio/x-pn-realaudio-plugin', + 'ra' => 'audio/x-realaudio', + 'rv' => 'video/vnd.rn-realvideo', + 'wav' => array('audio/x-wav', 'audio/wave', 'audio/wav'), + 'bmp' => array('image/bmp', 'image/x-bmp', 'image/x-bitmap', 'image/x-xbitmap', 'image/x-win-bitmap', 'image/x-windows-bmp', 'image/ms-bmp', 'image/x-ms-bmp', 'application/bmp', 'application/x-bmp', 'application/x-win-bitmap'), + 'gif' => 'image/gif', + 'jpeg' => array('image/jpeg', 'image/pjpeg'), + 'jpg' => array('image/jpeg', 'image/pjpeg'), + 'jpe' => array('image/jpeg', 'image/pjpeg'), + 'jp2' => array('image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'), + 'j2k' => array('image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'), + 'jpf' => array('image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'), + 'jpg2' => array('image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'), + 'jpx' => array('image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'), + 'jpm' => array('image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'), + 'mj2' => array('image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'), + 'mjp2' => array('image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'), + 'png' => array('image/png', 'image/x-png'), + 'tiff' => 'image/tiff', + 'tif' => 'image/tiff', + 'css' => array('text/css', 'text/plain'), + 'html' => array('text/html', 'text/plain'), + 'htm' => array('text/html', 'text/plain'), + 'shtml' => array('text/html', 'text/plain'), + 'txt' => 'text/plain', + 'text' => 'text/plain', + 'log' => array('text/plain', 'text/x-log'), + 'rtx' => 'text/richtext', + 'rtf' => 'text/rtf', + 'xml' => array('application/xml', 'text/xml', 'text/plain'), + 'xsl' => array('application/xml', 'text/xsl', 'text/xml'), + 'mpeg' => 'video/mpeg', + 'mpg' => 'video/mpeg', + 'mpe' => 'video/mpeg', + 'qt' => 'video/quicktime', + 'mov' => 'video/quicktime', + 'avi' => array('video/x-msvideo', 'video/msvideo', 'video/avi', 'application/x-troff-msvideo'), + 'movie' => 'video/x-sgi-movie', + 'doc' => array('application/msword', 'application/vnd.ms-office'), + 'docx' => array('application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/zip', 'application/msword', 'application/x-zip'), + 'dot' => array('application/msword', 'application/vnd.ms-office'), + 'dotx' => array('application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/zip', 'application/msword'), + 'xlsx' => array('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/zip', 'application/vnd.ms-excel', 'application/msword', 'application/x-zip'), + 'word' => array('application/msword', 'application/octet-stream'), + 'xl' => 'application/excel', + 'eml' => 'message/rfc822', + 'json' => array('application/json', 'text/json'), + 'pem' => array('application/x-x509-user-cert', 'application/x-pem-file', 'application/octet-stream'), + 'p10' => array('application/x-pkcs10', 'application/pkcs10'), + 'p12' => 'application/x-pkcs12', + 'p7a' => 'application/x-pkcs7-signature', + 'p7c' => array('application/pkcs7-mime', 'application/x-pkcs7-mime'), + 'p7m' => array('application/pkcs7-mime', 'application/x-pkcs7-mime'), + 'p7r' => 'application/x-pkcs7-certreqresp', + 'p7s' => 'application/pkcs7-signature', + 'crt' => array('application/x-x509-ca-cert', 'application/x-x509-user-cert', 'application/pkix-cert'), + 'crl' => array('application/pkix-crl', 'application/pkcs-crl'), + 'der' => 'application/x-x509-ca-cert', + 'kdb' => 'application/octet-stream', + 'pgp' => 'application/pgp', + 'gpg' => 'application/gpg-keys', + 'sst' => 'application/octet-stream', + 'csr' => 'application/octet-stream', + 'rsa' => 'application/x-pkcs7', + 'cer' => array('application/pkix-cert', 'application/x-x509-ca-cert'), + '3g2' => 'video/3gpp2', + '3gp' => array('video/3gp', 'video/3gpp'), + 'mp4' => 'video/mp4', + 'm4a' => 'audio/x-m4a', + 'f4v' => array('video/mp4', 'video/x-f4v'), + 'flv' => 'video/x-flv', + 'webm' => 'video/webm', + 'aac' => 'audio/x-acc', + 'm4u' => 'application/vnd.mpegurl', + 'm3u' => 'text/plain', + 'xspf' => 'application/xspf+xml', + 'vlc' => 'application/videolan', + 'wmv' => array('video/x-ms-wmv', 'video/x-ms-asf'), + 'au' => 'audio/x-au', + 'ac3' => 'audio/ac3', + 'flac' => 'audio/x-flac', + 'ogg' => array('audio/ogg', 'video/ogg', 'application/ogg'), + 'kmz' => array('application/vnd.google-earth.kmz', 'application/zip', 'application/x-zip'), + 'kml' => array('application/vnd.google-earth.kml+xml', 'application/xml', 'text/xml'), + 'ics' => 'text/calendar', + 'ical' => 'text/calendar', + 'zsh' => 'text/x-scriptzsh', + '7z' => array('application/x-7z-compressed', 'application/x-compressed', 'application/x-zip-compressed', 'application/zip', 'multipart/x-zip'), + '7zip' => array('application/x-7z-compressed', 'application/x-compressed', 'application/x-zip-compressed', 'application/zip', 'multipart/x-zip'), + 'cdr' => array('application/cdr', 'application/coreldraw', 'application/x-cdr', 'application/x-coreldraw', 'image/cdr', 'image/x-cdr', 'zz-application/zz-winassoc-cdr'), + 'wma' => array('audio/x-ms-wma', 'video/x-ms-asf'), + 'jar' => array('application/java-archive', 'application/x-java-application', 'application/x-jar', 'application/x-compressed'), + 'svg' => array('image/svg+xml', 'application/xml', 'text/xml'), + 'vcf' => 'text/x-vcard', + 'srt' => array('text/srt', 'text/plain'), + 'vtt' => array('text/vtt', 'text/plain'), + 'ico' => array('image/x-icon', 'image/x-ico', 'image/vnd.microsoft.icon'), + 'odc' => 'application/vnd.oasis.opendocument.chart', + 'otc' => 'application/vnd.oasis.opendocument.chart-template', + 'odf' => 'application/vnd.oasis.opendocument.formula', + 'otf' => 'application/vnd.oasis.opendocument.formula-template', + 'odg' => 'application/vnd.oasis.opendocument.graphics', + 'otg' => 'application/vnd.oasis.opendocument.graphics-template', + 'odi' => 'application/vnd.oasis.opendocument.image', + 'oti' => 'application/vnd.oasis.opendocument.image-template', + 'odp' => 'application/vnd.oasis.opendocument.presentation', + 'otp' => 'application/vnd.oasis.opendocument.presentation-template', + 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', + 'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template', + 'odt' => 'application/vnd.oasis.opendocument.text', + 'odm' => 'application/vnd.oasis.opendocument.text-master', + 'ott' => 'application/vnd.oasis.opendocument.text-template', + 'oth' => 'application/vnd.oasis.opendocument.text-web' +); diff --git a/src/application/config/profiler.php b/application/config/profiler.php similarity index 100% rename from src/application/config/profiler.php rename to application/config/profiler.php diff --git a/application/config/routes.php b/application/config/routes.php new file mode 100644 index 00000000..59c824cf --- /dev/null +++ b/application/config/routes.php @@ -0,0 +1,84 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +use EA\Engine\Notifications\Email as EmailClient; +use EA\Engine\Types\Email; +use EA\Engine\Types\Text; +use EA\Engine\Types\Url; + +/** + * Appointments Controller + * + * @property CI_Session $session + * @property CI_Loader $load + * @property CI_Input $input + * @property CI_Output $output + * @property CI_Config $config + * @property CI_Lang $lang + * @property CI_Cache $cache + * @property CI_DB_query_builder $db + * @property CI_Security $security + * @property Google_Sync $google_sync + * @property Ics_file $ics_file + * @property Appointments_Model $appointments_model + * @property Providers_Model $providers_model + * @property Services_Model $services_model + * @property Customers_Model $customers_model + * @property Settings_Model $settings_model + * @property Timezones $timezones + * @property Roles_Model $roles_model + * @property Secretaries_Model $secretaries_model + * @property Admins_Model $admins_model + * @property User_Model $user_model + * + * @package Controllers + */ +class Appointments extends CI_Controller { + /** + * Class Constructor + */ + public function __construct() + { + parent::__construct(); + + $this->load->library('session'); + $this->load->helper('installation'); + $this->load->helper('google_analytics'); + $this->load->model('appointments_model'); + $this->load->model('providers_model'); + $this->load->model('admins_model'); + $this->load->model('secretaries_model'); + $this->load->model('services_model'); + $this->load->model('customers_model'); + $this->load->model('settings_model'); + $this->load->library('timezones'); + + if ($this->session->userdata('language')) + { + // Set the user's selected language. + $this->config->set_item('language', $this->session->userdata('language')); + $this->lang->load('translations', $this->session->userdata('language')); + } + else + { + // Set the default language. + $this->lang->load('translations', $this->config->item('language')); + } + } + + /** + * Default callback method of the application. + * + * This method creates the appointment book wizard. If an appointment hash is provided then it means that the + * customer followed the appointment manage link that was send with the book success email. + * + * @param string $appointment_hash The appointment hash identifier. + */ + public function index($appointment_hash = '') + { + try + { + if ( ! is_app_installed()) + { + redirect('installation/index'); + return; + } + + $available_services = $this->services_model->get_available_services(); + $available_providers = $this->providers_model->get_available_providers(); + $company_name = $this->settings_model->get_setting('company_name'); + $book_advance_timeout = $this->settings_model->get_setting('book_advance_timeout'); + $date_format = $this->settings_model->get_setting('date_format'); + $time_format = $this->settings_model->get_setting('time_format'); + $first_weekday = $this->settings_model->get_setting('first_weekday'); + $require_phone_number = $this->settings_model->get_setting('require_phone_number'); + $display_cookie_notice = $this->settings_model->get_setting('display_cookie_notice'); + $cookie_notice_content = $this->settings_model->get_setting('cookie_notice_content'); + $display_terms_and_conditions = $this->settings_model->get_setting('display_terms_and_conditions'); + $terms_and_conditions_content = $this->settings_model->get_setting('terms_and_conditions_content'); + $display_privacy_policy = $this->settings_model->get_setting('display_privacy_policy'); + $privacy_policy_content = $this->settings_model->get_setting('privacy_policy_content'); + $display_any_provider = $this->settings_model->get_setting('display_any_provider'); + $timezones = $this->timezones->to_array(); + + // Remove the data that are not needed inside the $available_providers array. + foreach ($available_providers as $index => $provider) + { + $stripped_data = [ + 'id' => $provider['id'], + 'first_name' => $provider['first_name'], + 'last_name' => $provider['last_name'], + 'services' => $provider['services'], + 'timezone' => $provider['timezone'] + ]; + $available_providers[$index] = $stripped_data; + } + + // If an appointment hash is provided then it means that the customer is trying to edit a registered + // appointment record. + if ($appointment_hash !== '') + { + // Load the appointments data and enable the manage mode of the page. + $manage_mode = TRUE; + + $results = $this->appointments_model->get_batch(['hash' => $appointment_hash]); + + if (empty($results)) + { + // The requested appointment doesn't exist in the database. Display a message to the customer. + $variables = [ + 'message_title' => lang('appointment_not_found'), + 'message_text' => lang('appointment_does_not_exist_in_db'), + 'message_icon' => base_url('assets/img/error.png') + ]; + + $this->load->view('appointments/message', $variables); + + return; + } + + // If the requested apppointment begin date is lower than book_advance_timeout. Display + // a message to the customer. + $startDate = strtotime($results[0]['start_datetime']); + $limit = strtotime('+' . $book_advance_timeout . ' minutes', strtotime('now')); + + if ($startDate < $limit) + { + $hours = floor($book_advance_timeout / 60); + $minutes = ($book_advance_timeout % 60); + + $view = [ + 'message_title' => $this->lang->line('appointment_locked'), + 'message_text' => strtr($this->lang->line('appointment_locked_message'), [ + '{$limit}' => sprintf('%02d:%02d', $hours, $minutes) + ]), + 'message_icon' => base_url('assets/img/error.png') + ]; + $this->load->view('appointments/message', $view); + return; + } + + $appointment = $results[0]; + $provider = $this->providers_model->get_row($appointment['id_users_provider']); + $customer = $this->customers_model->get_row($appointment['id_users_customer']); + + $customer_token = md5(uniqid(mt_rand(), TRUE)); + + $this->load->driver('cache', ['adapter' => 'file']); + // Save the token for 10 minutes. + $this->cache->save('customer-token-' . $customer_token, $customer['id'], 600); + } + else + { + // The customer is going to book a new appointment so there is no need for the manage functionality to + // be initialized. + $manage_mode = FALSE; + $customer_token = FALSE; + $appointment = []; + $provider = []; + $customer = []; + } + + // Load the book appointment view. + $variables = [ + 'available_services' => $available_services, + 'available_providers' => $available_providers, + 'company_name' => $company_name, + 'manage_mode' => $manage_mode, + 'customer_token' => $customer_token, + 'date_format' => $date_format, + 'time_format' => $time_format, + 'first_weekday' => $first_weekday, + 'require_phone_number' => $require_phone_number, + 'appointment_data' => $appointment, + 'provider_data' => $provider, + 'customer_data' => $customer, + 'display_cookie_notice' => $display_cookie_notice, + 'cookie_notice_content' => $cookie_notice_content, + 'display_terms_and_conditions' => $display_terms_and_conditions, + 'terms_and_conditions_content' => $terms_and_conditions_content, + 'display_privacy_policy' => $display_privacy_policy, + 'privacy_policy_content' => $privacy_policy_content, + 'timezones' => $timezones, + 'display_any_provider' => $display_any_provider, + ]; + } + catch (Exception $exception) + { + $variables['exceptions'][] = $exception; + } + + $this->load->view('appointments/book', $variables); + } + + /** + * Cancel an existing appointment. + * + * This method removes an appointment from the company's schedule. In order for the appointment to be deleted, the + * hash string must be provided. The customer can only cancel the appointment if the edit time period is not over + * yet. + * + * @param string $appointment_hash This appointment hash identifier. + */ + public function cancel($appointment_hash) + { + try + { + // Check whether the appointment hash exists in the database. + $appointments = $this->appointments_model->get_batch(['hash' => $appointment_hash]); + + if (empty($appointments)) + { + throw new Exception('No record matches the provided hash.'); + } + + $appointment = $appointments[0]; + $provider = $this->providers_model->get_row($appointment['id_users_provider']); + $customer = $this->customers_model->get_row($appointment['id_users_customer']); + $service = $this->services_model->get_row($appointment['id_services']); + + $settings = [ + 'company_name' => $this->settings_model->get_setting('company_name'), + 'company_email' => $this->settings_model->get_setting('company_email'), + 'company_link' => $this->settings_model->get_setting('company_link'), + 'date_format' => $this->settings_model->get_setting('date_format'), + 'time_format' => $this->settings_model->get_setting('time_format') + ]; + + // Remove the appointment record from the data. + if ( ! $this->appointments_model->delete($appointment['id'])) + { + throw new Exception('Appointment could not be deleted from the database.'); + } + + // Remove the appointment from Google Calendar if needed. + if ($appointment['id_google_calendar'] != NULL) + { + try + { + $google_sync = filter_var( + $this->providers_model->get_setting('google_sync', $appointment['id_users_provider']), + FILTER_VALIDATE_BOOLEAN); + + if ($google_sync === TRUE) + { + $google_token = json_decode($this->providers_model + ->get_setting('google_token', $provider['id'])); + $this->load->library('Google_sync'); + $this->google_sync->refresh_token($google_token->refresh_token); + $this->google_sync->delete_appointment($provider, $appointment['id_google_calendar']); + } + } + catch (Exception $exception) + { + $exceptions[] = $exception; + } + } + + // Send email notification to customer and provider. + try + { + $email = new EmailClient($this, $this->config->config); + + $send_provider = filter_var($this->providers_model + ->get_setting('notifications', $provider['id']), + FILTER_VALIDATE_BOOLEAN); + + if ($send_provider === TRUE) + { + $email->sendDeleteAppointment($appointment, $provider, + $service, $customer, $settings, new Email($provider['email']), + new Text($this->input->post('cancel_reason'))); + } + + $send_customer = filter_var( + $this->settings_model->get_setting('customer_notifications'), + FILTER_VALIDATE_BOOLEAN); + + if ($send_customer === TRUE) + { + $email->sendDeleteAppointment($appointment, $provider, + $service, $customer, $settings, new Email($customer['email']), + new Text($this->input->post('cancel_reason'))); + } + + // Notify admins + $admins = $this->admins_model->get_batch(); + + foreach($admins as $admin) + { + if (!$admin['settings']['notifications'] === '0') + { + continue; + } + + $email->sendDeleteAppointment($appointment, $provider, + $service, $customer, $settings, new Email($admin['email']), + new Text($this->input->post('cancel_reason'))); + } + + // Notify secretaries + $secretaries = $this->secretaries_model->get_batch(); + + foreach($secretaries as $secretary) + { + if (!$secretary['settings']['notifications'] === '0') + { + continue; + } + + if (in_array($provider['id'], $secretary['providers'])) + { + continue; + } + + $email->sendDeleteAppointment($appointment, $provider, + $service, $customer, $settings, new Email($secretary['email']), + new Text($this->input->post('cancel_reason'))); + } + } + catch (Exception $exception) + { + $exceptions[] = $exception; + } + } + catch (Exception $exception) + { + // Display the error message to the customer. + $exceptions[] = $exception; + } + + $view = [ + 'message_title' => lang('appointment_cancelled_title'), + 'message_text' => lang('appointment_cancelled'), + 'message_icon' => base_url('assets/img/success.png') + ]; + + if (isset($exceptions)) + { + $view['exceptions'] = $exceptions; + } + + $this->load->view('appointments/message', $view); + } + + /** + * GET an specific appointment book and redirect to the success screen. + * + * @param string $appointment_hash The appointment hash identifier. + * + * @throws Exception + */ + public function book_success($appointment_hash) + { + $appointments = $this->appointments_model->get_batch(['hash' => $appointment_hash]); + + if (empty($appointments)) + { + redirect('appointments'); // The appointment does not exist. + return; + } + + $appointment = $appointments[0]; + unset($appointment['notes']); + + $provider = $this->providers_model->get_row($appointment['id_users_provider']); + unset($provider['settings'], $provider['notes']); + + $service = $this->services_model->get_row($appointment['id_services']); + + $company_name = $this->settings_model->get_setting('company_name'); + + // Get any pending exceptions. + $exceptions = $this->session->flashdata('book_success'); + + $view = [ + 'appointment_data' => $appointment, + 'provider_data' => $provider, + 'service_data' => $service, + 'company_name' => $company_name, + ]; + + if ($exceptions) + { + $view['exceptions'] = $exceptions; + } + + $this->load->view('appointments/book_success', $view); + } + + /** + * [AJAX] Get the available appointment hours for the given date. + * + * This method answers to an AJAX request. It calculates the available hours for the given service, provider and + * date. + * + * Outputs a JSON string with the availabilities. + */ + public function ajax_get_available_hours() + { + try + { + $provider_id = $this->input->post('provider_id'); + $service_id = $this->input->post('service_id'); + $selected_date = $this->input->post('selected_date'); + + // Do not continue if there was no provider selected (more likely there is no provider in the system). + if (empty($provider_id)) + { + $this->output + ->set_content_type('application/json') + ->set_output(json_encode([])); + + return; + } + + // If manage mode is TRUE then the following we should not consider the selected appointment when + // calculating the available time periods of the provider. + $exclude_appointments = []; + + if ($this->input->post('manage_mode') === 'true') + { + $exclude_appointments[] = $this->input->post('appointment_id'); + } + + // If the user has selected the "any-provider" option then we will need to search for an available provider + // that will provide the requested service. + if ($provider_id === ANY_PROVIDER) + { + $provider_id = $this->search_any_provider($service_id, $selected_date); + + if ($provider_id === NULL) + { + $this->output + ->set_content_type('application/json') + ->set_output(json_encode([])); + + return; + } + } + + $service = $this->services_model->get_row($service_id); + $provider = $this->providers_model->get_row($provider_id); + + $empty_periods = $this->get_provider_available_time_periods($provider_id, + $selected_date, $exclude_appointments); + + $available_hours = $this->calculate_available_hours($empty_periods, $selected_date, + $service['duration'], $service['availabilities_type']); + + if ($service['attendants_number'] > 1) + { + $available_hours = $this->get_multiple_attendants_hours($selected_date, $service, + $provider); + } + + $response = $this->consider_book_advance_timeout($selected_date, $available_hours, $provider); + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Search for any provider that can handle the requested service. + * + * This method will return the database ID of the provider with the most available periods. + * + * @param int $service_id The requested service ID. + * @param string $selected_date The date to be searched. + * + * @return int Returns the ID of the provider that can provide the service at the selected date. + * + * @throws Exception + */ + protected function search_any_provider($service_id, $selected_date) + { + $available_providers = $this->providers_model->get_available_providers(); + + $service = $this->services_model->get_row($service_id); + + $provider_id = NULL; + + $max_hours_count = 0; + + foreach ($available_providers as $provider) + { + foreach ($provider['services'] as $provider_service_id) + { + if ($provider_service_id == $service_id) + { + // Check if the provider is available for the requested date. + $empty_periods = $this->get_provider_available_time_periods($provider['id'], $selected_date); + + $available_hours = $this->calculate_available_hours($empty_periods, $selected_date, + $service['duration'], $service['availabilities_type']); + + if ($service['attendants_number'] > 1) + { + $available_hours = $this->get_multiple_attendants_hours($selected_date, $service, + $provider); + } + + if (count($available_hours) > $max_hours_count) + { + $provider_id = $provider['id']; + $max_hours_count = count($available_hours); + } + } + } + } + + return $provider_id; + } + + /** + * Get an array containing the free time periods (start - end) of a selected date. + * + * This method is very important because there are many cases where the system needs to know when a provider is + * available for an appointment. This method will return an array that belongs to the selected date and contains + * values that have the start and the end time of an available time period. + * + * @param int $provider_id Provider record ID. + * @param string $selected_date Date to be checked (MySQL formatted string). + * @param array $excluded_appointment_ids Array containing the IDs of the appointments that will not be taken into + * consideration when the available time periods are calculated. + * + * @return array Returns an array with the available time periods of the provider. + * + * @throws Exception + */ + protected function get_provider_available_time_periods( + $provider_id, + $selected_date, + $excluded_appointment_ids = [] + ) + { + // Get the service, provider's working plan and provider appointments. + $working_plan = json_decode($this->providers_model->get_setting('working_plan', $provider_id), TRUE); + + // Get the provider's working plan exceptions. + $working_plan_exceptions = json_decode($this->providers_model->get_setting('working_plan_exceptions', $provider_id), TRUE); + + $provider_appointments = $this->appointments_model->get_batch([ + 'id_users_provider' => $provider_id, + ]); + + // Sometimes it might be necessary to not take into account some appointment records in order to display what + // the providers' available time periods would be without them. + foreach ($excluded_appointment_ids as $excluded_appointment_id) + { + foreach ($provider_appointments as $index => $reserved) + { + if ($reserved['id'] == $excluded_appointment_id) + { + unset($provider_appointments[$index]); + } + } + } + + // Find the empty spaces on the plan. The first split between the plan is due to a break (if any). After that + // every reserved appointment is considered to be a taken space in the plan. + $selected_date_working_plan = $working_plan[strtolower(date('l', strtotime($selected_date)))]; + + // Search if the $selected_date is an custom availability period added outside the normal working plan. + if (isset($working_plan_exceptions[$selected_date])) + { + $selected_date_working_plan = $working_plan_exceptions[$selected_date]; + } + + $periods = []; + + if (isset($selected_date_working_plan['breaks'])) + { + $periods[] = [ + 'start' => $selected_date_working_plan['start'], + 'end' => $selected_date_working_plan['end'] + ]; + + $day_start = new DateTime($selected_date_working_plan['start']); + $day_end = new DateTime($selected_date_working_plan['end']); + + // Split the working plan to available time periods that do not contain the breaks in them. + foreach ($selected_date_working_plan['breaks'] as $index => $break) + { + $break_start = new DateTime($break['start']); + $break_end = new DateTime($break['end']); + + if ($break_start < $day_start) + { + $break_start = $day_start; + } + + if ($break_end > $day_end) + { + $break_end = $day_end; + } + + if ($break_start >= $break_end) + { + continue; + } + + foreach ($periods as $key => $period) + { + $period_start = new DateTime($period['start']); + $period_end = new DateTime($period['end']); + + $remove_current_period = FALSE; + + if ($break_start > $period_start && $break_start < $period_end && $break_end > $period_start) + { + $periods[] = [ + 'start' => $period_start->format('H:i'), + 'end' => $break_start->format('H:i') + ]; + + $remove_current_period = TRUE; + } + + if ($break_start < $period_end && $break_end > $period_start && $break_end < $period_end) + { + $periods[] = [ + 'start' => $break_end->format('H:i'), + 'end' => $period_end->format('H:i') + ]; + + $remove_current_period = TRUE; + } + + if ($break_start == $period_start && $break_end == $period_end) + { + $remove_current_period = TRUE; + } + + if ($remove_current_period) + { + unset($periods[$key]); + } + } + } + } + + // Break the empty periods with the reserved appointments. + foreach ($provider_appointments as $provider_appointment) + { + foreach ($periods as $index => &$period) + { + $appointment_start = new DateTime($provider_appointment['start_datetime']); + $appointment_end = new DateTime($provider_appointment['end_datetime']); + + if ($appointment_start >= $appointment_end) + { + continue; + } + + $period_start = new DateTime($selected_date . ' ' . $period['start']); + $period_end = new DateTime($selected_date . ' ' . $period['end']); + + if ($appointment_start <= $period_start && $appointment_end <= $period_end && $appointment_end <= $period_start) + { + // The appointment does not belong in this time period, so we will not change anything. + continue; + } + else + { + if ($appointment_start <= $period_start && $appointment_end <= $period_end && $appointment_end >= $period_start) + { + // The appointment starts before the period and finishes somewhere inside. We will need to break + // this period and leave the available part. + $period['start'] = $appointment_end->format('H:i'); + } + else + { + if ($appointment_start >= $period_start && $appointment_end < $period_end) + { + // The appointment is inside the time period, so we will split the period into two new + // others. + unset($periods[$index]); + + $periods[] = [ + 'start' => $period_start->format('H:i'), + 'end' => $appointment_start->format('H:i') + ]; + + $periods[] = [ + 'start' => $appointment_end->format('H:i'), + 'end' => $period_end->format('H:i') + ]; + } + else if ($appointment_start == $period_start && $appointment_end == $period_end) + { + unset($periods[$index]); // The whole period is blocked so remove it from the available periods array. + } + else + { + if ($appointment_start >= $period_start && $appointment_end >= $period_start && $appointment_start <= $period_end) + { + // The appointment starts in the period and finishes out of it. We will need to remove + // the time that is taken from the appointment. + $period['end'] = $appointment_start->format('H:i'); + } + else + { + if ($appointment_start >= $period_start && $appointment_end >= $period_end && $appointment_start >= $period_end) + { + // The appointment does not belong in the period so do not change anything. + continue; + } + else + { + if ($appointment_start <= $period_start && $appointment_end >= $period_end && $appointment_start <= $period_end) + { + // The appointment is bigger than the period, so this period needs to be removed. + unset($periods[$index]); + } + } + } + } + } + } + } + } + + return array_values($periods); + } + + /** + * Calculate the available appointment hours. + * + * Calculate the available appointment hours for the given date. The empty spaces + * are broken down to 15 min and if the service fit in each quarter then a new + * available hour is added to the "$available_hours" array. + * + * @param array $empty_periods Contains the empty periods as generated by the "get_provider_available_time_periods" + * method. + * @param string $selected_date The selected date to be search (format ) + * @param int $service_duration The service duration is required for the hour calculation. + * @param string $availabilities_type Optional ('flexible'), the service availabilities type. + * + * @return array Returns an array with the available hours for the appointment. + * @throws Exception + */ + protected function calculate_available_hours( + array $empty_periods, + $selected_date, + $service_duration, + $availabilities_type = 'flexible' + ) + { + $available_hours = []; + + foreach ($empty_periods as $period) + { + $start_hour = new DateTime($selected_date . ' ' . $period['start']); + $end_hour = new DateTime($selected_date . ' ' . $period['end']); + $interval = $availabilities_type === AVAILABILITIES_TYPE_FIXED ? (int)$service_duration : 15; + + $current_hour = $start_hour; + $diff = $current_hour->diff($end_hour); + + while (($diff->h * 60 + $diff->i) >= intval($service_duration)) + { + $available_hours[] = $current_hour->format('H:i'); + $current_hour->add(new DateInterval('PT' . $interval . 'M')); + $diff = $current_hour->diff($end_hour); + } + } + + return $available_hours; + } + + /** + * Get multiple attendants hours. + * + * This method will add the additional appointment hours whenever a service accepts multiple attendants. + * + * @param string $selected_date The selected appointment date. + * @param array $service Selected service data. + * @param array $provider Selected provider data. + * + * @return array Returns the available hours array. + * @throws Exception + */ + protected function get_multiple_attendants_hours( + $selected_date, + $service, + $provider + ) + { + $unavailability_events = $this->appointments_model->get_batch([ + 'is_unavailable' => TRUE, + 'DATE(start_datetime)' => $selected_date, + 'id_users_provider' => $provider['id'] + ]); + + $working_plan = json_decode($provider['settings']['working_plan'], TRUE); + $working_day = strtolower(date('l', strtotime($selected_date))); + $working_hours = $working_plan[$working_day]; + + $periods = [ + [ + 'start' => new DateTime($selected_date . ' ' . $working_hours['start']), + 'end' => new DateTime($selected_date . ' ' . $working_hours['end']) + ] + ]; + + $periods = $this->remove_breaks($selected_date, $periods, $working_hours['breaks']); + $periods = $this->remove_unavailability_events($periods, $unavailability_events); + + $hours = []; + + $interval_value = $service['availabilities_type'] == AVAILABILITIES_TYPE_FIXED ? $service['duration'] : '15'; + $interval = new DateInterval('PT' . (int)$interval_value . 'M'); + $duration = new DateInterval('PT' . (int)$service['duration'] . 'M'); + + foreach ($periods as $period) + { + $slot_start = clone $period['start']; + $slot_end = clone $slot_start; + $slot_end->add($duration); + + while ($slot_end <= $period['end']) + { + // Check reserved attendants for this time slot and see if current attendants fit. + $appointment_attendants_number = $this->appointments_model->get_attendants_number_for_period($slot_start, + $slot_end, $service['id']); + + if ($appointment_attendants_number < $service['attendants_number']) + { + $hours[] = $slot_start->format('H:i'); + } + + $slot_start->add($interval); + $slot_end->add($interval); + } + } + + return $hours; + } + + /** + * Remove breaks from available time periods. + * + * @param string $selected_date Selected data (Y-m-d format). + * @param array $periods Time periods of the current date. + * @param array $breaks Breaks array for the current date. + * + * @return array Returns the available time periods without the breaks. + * @throws Exception + */ + public function remove_breaks($selected_date, $periods, $breaks) + { + if ( ! $breaks) + { + return $periods; + } + + foreach ($breaks as $break) + { + $break_start = new DateTime($selected_date . ' ' . $break['start']); + $break_end = new DateTime($selected_date . ' ' . $break['end']); + + foreach ($periods as &$period) + { + $period_start = $period['start']; + $period_end = $period['end']; + + if ($break_start <= $period_start && $break_end >= $period_start && $break_end <= $period_end) + { + // left + $period['start'] = $break_end; + continue; + } + + if ($break_start >= $period_start && $break_start <= $period_end && $break_end >= $period_start && $break_end <= $period_end) + { + // middle + $period['end'] = $break_start; + $periods[] = [ + 'start' => $break_end, + 'end' => $period_end + ]; + continue; + } + + if ($break_start >= $period_start && $break_start <= $period_end && $break_end >= $period_end) + { + // right + $period['end'] = $break_start; + continue; + } + + if ($break_start <= $period_start && $break_end >= $period_end) + { + // break contains period + $period['start'] = $break_end; + continue; + } + } + } + + return $periods; + } + + /** + * Remove the unavailability entries from the available time periods of the selected date. + * + * @param array $periods Available time periods. + * @param array $unavailability_events Unavailability events of the current date. + * + * @return array Returns the available time periods without the unavailability events. + * + * @throws Exception + */ + public function remove_unavailability_events($periods, $unavailability_events) + { + foreach ($unavailability_events as $unavailability_event) + { + $unavailability_start = new DateTime($unavailability_event['start_datetime']); + $unavailability_end = new DateTime($unavailability_event['end_datetime']); + + foreach ($periods as &$period) + { + $period_start = $period['start']; + $period_end = $period['end']; + + if ($unavailability_start <= $period_start && $unavailability_end >= $period_start && $unavailability_end <= $period_end) + { + // left + $period['start'] = $unavailability_end; + continue; + } + + if ($unavailability_start >= $period_start && $unavailability_start <= $period_end && $unavailability_end >= $period_start && $unavailability_end <= $period_end) + { + // middle + $period['end'] = $unavailability_start; + $periods[] = [ + 'start' => $unavailability_end, + 'end' => $period_end + ]; + continue; + } + + if ($unavailability_start >= $period_start && $unavailability_start <= $period_end && $unavailability_end >= $period_end) + { + // right + $period['end'] = $unavailability_start; + continue; + } + + if ($unavailability_start <= $period_start && $unavailability_end >= $period_end) + { + // Unavailability contains period + $period['start'] = $unavailability_end; + continue; + } + } + } + + return $periods; + } + + /** + * [AJAX] Register the appointment to the database. + * + * Outputs a JSON string with the appointment ID. + */ + public function ajax_register_appointment() + { + try + { + $this->load->model('appointments_model'); + $this->load->model('providers_model'); + $this->load->model('admins_model'); + $this->load->model('secretaries_model'); + $this->load->model('services_model'); + $this->load->model('customers_model'); + $this->load->model('settings_model'); + + $post_data = $this->input->post('post_data'); + $captcha = $this->input->post('captcha'); + $manage_mode = filter_var($post_data['manage_mode'], FILTER_VALIDATE_BOOLEAN); + $appointment = $post_data['appointment']; + $customer = $post_data['customer']; + + // Check appointment availability before registering it to the database. + $appointment['id_users_provider'] = $this->check_datetime_availability(); + + if ( ! $appointment['id_users_provider']) + { + throw new Exception(lang('requested_hour_is_unavailable')); + } + + $provider = $this->providers_model->get_row($appointment['id_users_provider']); + $service = $this->services_model->get_row($appointment['id_services']); + + $require_captcha = $this->settings_model->get_setting('require_captcha'); + $captcha_phrase = $this->session->userdata('captcha_phrase'); + + // Validate the CAPTCHA string. + if ($require_captcha === '1' && $captcha_phrase !== $captcha) + { + $this->output + ->set_content_type('application/json') + ->set_output(json_encode([ + 'captcha_verification' => FALSE + ])); + + return; + } + + if ($this->customers_model->exists($customer)) + { + $customer['id'] = $this->customers_model->find_record_id($customer); + } + + if (empty($appointment['location']) && ! empty($service['location'])) + { + $appointment['location'] = $service['location']; + } + + // Save customer language (the language which is used to render the booking page). + $customer['language'] = $this->config->item('language'); + $customer_id = $this->customers_model->add($customer); + + $appointment['id_users_customer'] = $customer_id; + $appointment['is_unavailable'] = (int)$appointment['is_unavailable']; // needs to be type casted + $appointment['id'] = $this->appointments_model->add($appointment); + $appointment['hash'] = $this->appointments_model->get_value('hash', $appointment['id']); + + $settings = [ + 'company_name' => $this->settings_model->get_setting('company_name'), + 'company_link' => $this->settings_model->get_setting('company_link'), + 'company_email' => $this->settings_model->get_setting('company_email'), + 'date_format' => $this->settings_model->get_setting('date_format'), + 'time_format' => $this->settings_model->get_setting('time_format') + ]; + + // Synchronize the appointment with the provider's Google Calendar. + try + { + $google_sync = filter_var( + $this->providers_model->get_setting('google_sync', $appointment['id_users_provider']), + FILTER_VALIDATE_BOOLEAN); + + if ($google_sync === TRUE) + { + $google_token = json_decode( + $this->providers_model->get_setting('google_token', $appointment['id_users_provider'])); + + $this->load->library('google_sync'); + + $this->google_sync->refresh_token($google_token->refresh_token); + + if ($manage_mode === FALSE) + { + // Add appointment to Google Calendar. + $google_event = $this->google_sync->add_appointment($appointment, $provider, + $service, $customer, $settings); + $appointment['id_google_calendar'] = $google_event->id; + $this->appointments_model->add($appointment); + } + else + { + // Update appointment to Google Calendar. + $appointment['id_google_calendar'] = $this->appointments_model + ->get_value('id_google_calendar', $appointment['id']); + + $this->google_sync->update_appointment($appointment, $provider, + $service, $customer, $settings); + } + } + } + catch (Exception $exception) + { + log_message('error', $exception->getMessage()); + log_message('error', $exception->getTraceAsString()); + } + + // Send email notifications to customer and provider. + try + { + $this->config->load('email'); + + $email = new EmailClient($this, $this->config->config); + + if ($manage_mode === FALSE) + { + $customer_title = new Text(lang('appointment_booked')); + $customer_message = new Text(lang('thank_you_for_appointment')); + $provider_title = new Text(lang('appointment_added_to_your_plan')); + $provider_message = new Text(lang('appointment_link_description')); + + } + else + { + $customer_title = new Text(lang('appointment_changes_saved')); + $customer_message = new Text(''); + $provider_title = new Text(lang('appointment_details_changed')); + $provider_message = new Text(''); + } + + $customer_link = new Url(site_url('appointments/index/' . $appointment['hash'])); + $provider_link = new Url(site_url('backend/index/' . $appointment['hash'])); + + $send_customer = filter_var( + $this->settings_model->get_setting('customer_notifications'), + FILTER_VALIDATE_BOOLEAN); + + $this->load->library('ics_file'); + + $ics_stream = $this->ics_file->get_stream($appointment, $service, $provider, $customer); + + if ($send_customer === TRUE) + { + $email->sendAppointmentDetails($appointment, $provider, + $service, $customer, $settings, $customer_title, + $customer_message, $customer_link, new Email($customer['email']), new Text($ics_stream)); + } + + $send_provider = filter_var( + $this->providers_model->get_setting('notifications', $provider['id']), + FILTER_VALIDATE_BOOLEAN); + + if ($send_provider === TRUE) + { + $email->sendAppointmentDetails($appointment, $provider, + $service, $customer, $settings, $provider_title, + $provider_message, $provider_link, new Email($provider['email']), new Text($ics_stream)); + } + + // Notify admins + $admins = $this->admins_model->get_batch(); + + foreach($admins as $admin) + { + if (!$admin['settings']['notifications'] === '0') + { + continue; + } + + $email->sendAppointmentDetails($appointment, $provider, + $service, $customer, $settings, $provider_title, + $provider_message, $provider_link, new Email($admin['email']), new Text($ics_stream)); + } + + // Notify secretaries + $secretaries = $this->secretaries_model->get_batch(); + + foreach($secretaries as $secretary) + { + if (!$secretary['settings']['notifications'] === '0') + { + continue; + } + + if (in_array($provider['id'], $secretary['providers'])) + { + continue; + } + + $email->sendAppointmentDetails($appointment, $provider, + $service, $customer, $settings, $provider_title, + $provider_message, $provider_link, new Email($secretary['email']), new Text($ics_stream)); + } + } + catch (Exception $exception) + { + log_message('error', $exception->getMessage()); + log_message('error', $exception->getTraceAsString()); + } + + $response = [ + 'appointment_id' => $appointment['id'], + 'appointment_hash' => $appointment['hash'] + ]; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Check whether the provider is still available in the selected appointment date. + * + * It might be times where two or more customers select the same appointment date and time. This shouldn't be + * allowed to happen, so one of the two customers will eventually get the preferred date and the other one will have + * to choose for another date. Use this method just before the customer confirms the appointment details. If the + * selected date was taken in the mean time, the customer must be prompted to select another time for his + * appointment. + * + * @return int Returns the ID of the provider that is available for the appointment. + * + * @throws Exception + */ + protected function check_datetime_availability() + { + $this->load->model('services_model'); + $this->load->model('appointments_model'); + + $post_data = $this->input->post('post_data'); + + $appointment = $post_data['appointment']; + + $service_duration = $this->services_model->get_value('duration', $appointment['id_services']); + + $exclude_appointments = []; + + if (isset($appointment['id'])) + { + $exclude_appointments[] = $appointment['id']; + } + + $attendants_number = $this->services_model->get_value('attendants_number', $appointment['id_services']); + + if ($attendants_number > 1) + { + // Exclude all the appointments that are currently registered. + $existing_appointments = $this->appointments_model->get_batch([ + 'id_services' => $appointment['id_services'], + 'start_datetime' => $appointment['start_datetime'] + ]); + + if ( ! empty($existing_appointments) && count($existing_appointments) < $attendants_number) + { + foreach ($existing_appointments as $existing_appointment) + { + $exclude_appointments[] = $existing_appointment['id']; + } + } + } + + if ($appointment['id_users_provider'] === ANY_PROVIDER) + { + $appointment['id_users_provider'] = $this->search_any_provider($appointment['id_services'], + date('Y-m-d', strtotime($appointment['start_datetime']))); + + return $appointment['id_users_provider']; + } + + $available_periods = $this->get_provider_available_time_periods( + $appointment['id_users_provider'], + date('Y-m-d', strtotime($appointment['start_datetime'])), + $exclude_appointments); + + $is_still_available = FALSE; + + foreach ($available_periods as $period) + { + $appt_start = new DateTime($appointment['start_datetime']); + $appt_start = $appt_start->format('H:i'); + + $appt_end = new DateTime($appointment['start_datetime']); + $appt_end->add(new DateInterval('PT' . $service_duration . 'M')); + $appt_end = $appt_end->format('H:i'); + + $period_start = date('H:i', strtotime($period['start'])); + $period_end = date('H:i', strtotime($period['end'])); + + if ($period_start <= $appt_start && $period_end >= $appt_end) + { + $is_still_available = TRUE; + break; + } + } + + return $is_still_available ? $appointment['id_users_provider'] : NULL; + } + + /** + * [AJAX] Get Unavailable Dates + * + * Get an array with the available dates of a specific provider, service and month of the year. Provide the + * "provider_id", "service_id" and "selected_date" as GET parameters to the request. The "selected_date" parameter + * must have the Y-m-d format. + * + * Outputs a JSON string with the unavailable dates. that are unavailable. + */ + public function ajax_get_unavailable_dates() + { + try + { + $this->load->model('providers_model'); + $this->load->model('services_model'); + + $provider_id = $this->input->get('provider_id'); + $service_id = $this->input->get('service_id'); + $appointment_id = $this->input->get_post('appointment_id'); + $manage_mode = $this->input->get_post('manage_mode'); + $selected_date_string = $this->input->get('selected_date'); + $selected_date = new DateTime($selected_date_string); + $number_of_days_in_month = (int)$selected_date->format('t'); + $unavailable_dates = []; + + $exclude_appointments = []; + + if ($manage_mode === 'true') + { + $exclude_appointments[] = $appointment_id; + } + + $provider_list = $provider_id === ANY_PROVIDER + ? $this->search_providers_by_service($service_id) + : [$provider_id]; + + // Get the service record. + $service = $this->services_model->get_row($service_id); + + for ($i = 1; $i <= $number_of_days_in_month; $i++) + { + $current_date = new DateTime($selected_date->format('Y-m') . '-' . $i); + + if ($current_date < new DateTime(date('Y-m-d 00:00:00'))) + { + // Past dates become immediately unavailable. + $unavailable_dates[] = $current_date->format('Y-m-d'); + continue; + } + + // Finding at least one slot of availability. + foreach ($provider_list as $current_provider_id) + { + // Get the provider record. + $current_provider = $this->providers_model->get_row($current_provider_id); + + $empty_periods = $this->get_provider_available_time_periods($current_provider_id, + $current_date->format('Y-m-d'), $exclude_appointments); + + $available_hours = $this->calculate_available_hours($empty_periods, $current_date->format('Y-m-d'), + $service['duration'], $service['availabilities_type']); + + if ( ! empty($available_hours)) + { + break; + } + + if ($service['attendants_number'] > 1) + { + $available_hours = $this->get_multiple_attendants_hours($current_date->format('Y-m-d'), + $service, $current_provider); + + if ( ! empty($available_hours)) + { + break; + } + } + + $available_hours = $this->consider_book_advance_timeout($current_date->format('Y-m-d'), + $available_hours, $current_provider); + } + + // No availability amongst all the provider. + if (empty($available_hours)) + { + $unavailable_dates[] = $current_date->format('Y-m-d'); + } + } + + $response = $unavailable_dates; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Search for any provider that can handle the requested service. + * + * This method will return the database ID of the providers affected to the requested service. + * + * @param int $service_id The requested service ID. + * + * @return array Returns the ID of the provider that can provide the requested service. + */ + protected function search_providers_by_service($service_id) + { + $this->load->model('providers_model'); + $available_providers = $this->providers_model->get_available_providers(); + $provider_list = []; + + foreach ($available_providers as $provider) + { + foreach ($provider['services'] as $provider_service_id) + { + if ($provider_service_id === $service_id) + { + // Check if the provider is affected to the selected service. + $provider_list[] = $provider['id']; + } + } + } + + return $provider_list; + } + + /** + * Consider the book advance timeout and remove available hours that have passed the threshold. + * + * If the selected date is today, remove past hours. It is important include the timeout before booking + * that is set in the back-office the system. Normally we might want the customer to book an appointment + * that is at least half or one hour from now. The setting is stored in minutes. + * + * @param string $selected_date The selected date. + * @param array $available_hours Already generated available hours. + * @param array $provider Provider information. + * + * @return array Returns the updated available hours. + * + * @throws Exception + */ + protected function consider_book_advance_timeout($selected_date, $available_hours, $provider) + { + $provider_timezone = new DateTimeZone($provider['timezone']); + + $book_advance_timeout = $this->settings_model->get_setting('book_advance_timeout'); + + $threshold = new DateTime('+' . $book_advance_timeout . ' minutes', $provider_timezone); + + foreach ($available_hours as $index => $value) + { + $available_hour = new DateTime($selected_date . ' ' . $value, $provider_timezone); + + if ($available_hour->getTimestamp() <= $threshold->getTimestamp()) + { + unset($available_hours[$index]); + } + } + + $available_hours = array_values($available_hours); + sort($available_hours, SORT_STRING); + return array_values($available_hours); + } +} diff --git a/application/controllers/Backend.php b/application/controllers/Backend.php new file mode 100755 index 00000000..10036304 --- /dev/null +++ b/application/controllers/Backend.php @@ -0,0 +1,431 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +/** + * Backend Controller + * + * @property CI_Session $session + * @property CI_Loader $load + * @property CI_Input $input + * @property CI_Output $output + * @property CI_Config $config + * @property CI_Lang $lang + * @property CI_Cache $cache + * @property CI_DB_query_builder $db + * @property CI_Security $security + * @property Google_Sync $google_sync + * @property Ics_file $ics_file + * @property Appointments_Model $appointments_model + * @property Providers_Model $providers_model + * @property Services_Model $services_model + * @property Customers_Model $customers_model + * @property Settings_Model $settings_model + * @property Timezones $timezones + * @property Roles_Model $roles_model + * @property Secretaries_Model $secretaries_model + * @property Admins_Model $admins_model + * @property User_Model $user_model + * + * @package Controllers + */ +class Backend extends CI_Controller { + /** + * Class Constructor + */ + public function __construct() + { + parent::__construct(); + $this->load->library('session'); + + if ($this->session->userdata('language')) + { + // Set user's selected language. + $this->config->set_item('language', $this->session->userdata('language')); + $this->lang->load('translations', $this->session->userdata('language')); + } + else + { + // Set the default language. + $this->lang->load('translations', $this->config->item('language')); + } + } + + /** + * Display the main backend page. + * + * This method displays the main backend page. All users login permission can view this page which displays a + * calendar with the events of the selected provider or service. If a user has more privileges he will see more + * menus at the top of the page. + * + * @param string $appointment_hash Appointment edit dialog will appear when the page loads (default ''). + * + * @throws Exception + */ + public function index($appointment_hash = '') + { + $this->session->set_userdata('dest_url', site_url('backend/index' . (!empty($appointment_hash) ? '/' . $appointment_hash : ''))); + + if ( ! $this->has_privileges(PRIV_APPOINTMENTS)) + { + return; + } + + $this->load->model('appointments_model'); + $this->load->model('providers_model'); + $this->load->model('services_model'); + $this->load->model('customers_model'); + $this->load->model('settings_model'); + $this->load->model('roles_model'); + $this->load->model('user_model'); + $this->load->model('secretaries_model'); + $this->load->library('timezones'); + + $calendar_view_query_param = $this->input->get('view'); + + $user_id = $this->session->userdata('user_id'); + + $user = $this->user_model->get_user($user_id); + + $view['base_url'] = $this->config->item('base_url'); + $view['page_title'] = lang('calendar'); + $view['user_display_name'] = $this->user_model->get_user_display_name($this->session->userdata('user_id')); + $view['active_menu'] = PRIV_APPOINTMENTS; + $view['date_format'] = $this->settings_model->get_setting('date_format'); + $view['time_format'] = $this->settings_model->get_setting('time_format'); + $view['first_weekday'] = $this->settings_model->get_setting('first_weekday'); + $view['company_name'] = $this->settings_model->get_setting('company_name'); + $view['require_phone_number'] = $this->settings_model->get_setting('require_phone_number'); + $view['available_providers'] = $this->providers_model->get_available_providers(); + $view['available_services'] = $this->services_model->get_available_services(); + $view['customers'] = $this->customers_model->get_batch(); + $view['calendar_view'] = !empty($calendar_view_query_param) ? $calendar_view_query_param : $user['settings']['calendar_view']; + $view['timezones'] = $this->timezones->to_array(); + $this->set_user_data($view); + + if ($this->session->userdata('role_slug') === DB_SLUG_SECRETARY) + { + $secretary = $this->secretaries_model->get_row($this->session->userdata('user_id')); + $view['secretary_providers'] = $secretary['providers']; + } + else + { + $view['secretary_providers'] = []; + } + + $results = $this->appointments_model->get_batch(['hash' => $appointment_hash]); + + if ($appointment_hash !== '' && count($results) > 0) + { + $appointment = $results[0]; + $appointment['customer'] = $this->customers_model->get_row($appointment['id_users_customer']); + $view['edit_appointment'] = $appointment; // This will display the appointment edit dialog on page load. + } + else + { + $view['edit_appointment'] = NULL; + } + + $this->load->view('backend/header', $view); + $this->load->view('backend/calendar', $view); + $this->load->view('backend/footer', $view); + } + + /** + * Check whether current user is logged in and has the required privileges to view a page. + * + * The backend page requires different privileges from the users to display pages. Not all pages are available to + * all users. For example secretaries should not be able to edit the system users. + * + * @param string $page This argument must match the roles field names of each section (eg "appointments", "users" + * ...). + * @param bool $redirect If the user has not the required privileges (either not logged in or insufficient role + * privileges) then the user will be redirected to another page. Set this argument to FALSE when using ajax (default + * true). + * + * @return bool Returns whether the user has the required privileges to view the page or not. If the user is not + * logged in then he will be prompted to log in. If he hasn't the required privileges then an info message will be + * displayed. + */ + protected function has_privileges($page, $redirect = TRUE) + { + // Check if user is logged in. + $user_id = $this->session->userdata('user_id'); + + if ($user_id == FALSE) + { + // User not logged in, display the login view. + if ($redirect) + { + header('Location: ' . site_url('user/login')); + } + return FALSE; + } + + // Check if the user has the required privileges for viewing the selected page. + $role_slug = $this->session->userdata('role_slug'); + + $role_privileges = $this->db->get_where('roles', ['slug' => $role_slug])->row_array(); + + if ($role_privileges[$page] < PRIV_VIEW) + { + // User does not have the permission to view the page. + if ($redirect) + { + header('Location: ' . site_url('user/no_privileges')); + } + return FALSE; + } + + return TRUE; + } + + /** + * Set the user data in order to be available at the view and js code. + * + * @param array $view Contains the view data. + */ + protected function set_user_data(&$view) + { + $this->load->model('roles_model'); + + // Get privileges + $view['user_id'] = $this->session->userdata('user_id'); + $view['user_email'] = $this->session->userdata('user_email'); + $view['timezone'] = $this->session->userdata('timezone'); + $view['role_slug'] = $this->session->userdata('role_slug'); + $view['privileges'] = $this->roles_model->get_privileges($this->session->userdata('role_slug')); + } + + /** + * Display the backend customers page. + * + * In this page the user can manage all the customer records of the system. + */ + public function customers() + { + $this->session->set_userdata('dest_url', site_url('backend/customers')); + + if ( ! $this->has_privileges(PRIV_CUSTOMERS)) + { + return; + } + + $this->load->model('providers_model'); + $this->load->model('customers_model'); + $this->load->model('secretaries_model'); + $this->load->model('services_model'); + $this->load->model('settings_model'); + $this->load->model('user_model'); + $this->load->library('timezones'); + + $view['base_url'] = $this->config->item('base_url'); + $view['page_title'] = lang('customers'); + $view['user_display_name'] = $this->user_model->get_user_display_name($this->session->userdata('user_id')); + $view['active_menu'] = PRIV_CUSTOMERS; + $view['company_name'] = $this->settings_model->get_setting('company_name'); + $view['date_format'] = $this->settings_model->get_setting('date_format'); + $view['time_format'] = $this->settings_model->get_setting('time_format'); + $view['first_weekday'] = $this->settings_model->get_setting('first_weekday'); + $view['require_phone_number'] = $this->settings_model->get_setting('require_phone_number'); + $view['customers'] = $this->customers_model->get_batch(); + $view['available_providers'] = $this->providers_model->get_available_providers(); + $view['available_services'] = $this->services_model->get_available_services(); + $view['timezones'] = $this->timezones->to_array(); + + if ($this->session->userdata('role_slug') === DB_SLUG_SECRETARY) + { + $secretary = $this->secretaries_model->get_row($this->session->userdata('user_id')); + $view['secretary_providers'] = $secretary['providers']; + } + else + { + $view['secretary_providers'] = []; + } + + $this->set_user_data($view); + + $this->load->view('backend/header', $view); + $this->load->view('backend/customers', $view); + $this->load->view('backend/footer', $view); + } + + /** + * Displays the backend services page. + * + * Here the admin user will be able to organize and create the services that the user will be able to book + * appointments in frontend. + * + * NOTICE: The services that each provider is able to service is managed from the backend services page. + */ + public function services() + { + $this->session->set_userdata('dest_url', site_url('backend/services')); + + if ( ! $this->has_privileges(PRIV_SERVICES)) + { + return; + } + + $this->load->model('customers_model'); + $this->load->model('services_model'); + $this->load->model('settings_model'); + $this->load->model('user_model'); + $this->load->library('timezones'); + + $view['base_url'] = $this->config->item('base_url'); + $view['page_title'] = lang('services'); + $view['user_display_name'] = $this->user_model->get_user_display_name($this->session->userdata('user_id')); + $view['active_menu'] = PRIV_SERVICES; + $view['company_name'] = $this->settings_model->get_setting('company_name'); + $view['date_format'] = $this->settings_model->get_setting('date_format'); + $view['time_format'] = $this->settings_model->get_setting('time_format'); + $view['first_weekday'] = $this->settings_model->get_setting('first_weekday'); + $view['services'] = $this->services_model->get_batch(); + $view['categories'] = $this->services_model->get_all_categories(); + $view['timezones'] = $this->timezones->to_array(); + $this->set_user_data($view); + + $this->load->view('backend/header', $view); + $this->load->view('backend/services', $view); + $this->load->view('backend/footer', $view); + } + + /** + * Display the backend users page. + * + * In this page the admin user will be able to manage the system users. By this, we mean the provider, secretary and + * admin users. This is also the page where the admin defines which service can each provider provide. + */ + public function users() + { + $this->session->set_userdata('dest_url', site_url('backend/users')); + + if ( ! $this->has_privileges(PRIV_USERS)) + { + return; + } + + $this->load->model('providers_model'); + $this->load->model('secretaries_model'); + $this->load->model('admins_model'); + $this->load->model('services_model'); + $this->load->model('settings_model'); + $this->load->model('user_model'); + $this->load->library('timezones'); + + $view['base_url'] = $this->config->item('base_url'); + $view['page_title'] = lang('users'); + $view['user_display_name'] = $this->user_model->get_user_display_name($this->session->userdata('user_id')); + $view['active_menu'] = PRIV_USERS; + $view['company_name'] = $this->settings_model->get_setting('company_name'); + $view['date_format'] = $this->settings_model->get_setting('date_format'); + $view['time_format'] = $this->settings_model->get_setting('time_format'); + $view['first_weekday'] = $this->settings_model->get_setting('first_weekday'); + $view['admins'] = $this->admins_model->get_batch(); + $view['providers'] = $this->providers_model->get_batch(); + $view['secretaries'] = $this->secretaries_model->get_batch(); + $view['services'] = $this->services_model->get_batch(); + $view['working_plan'] = $this->settings_model->get_setting('company_working_plan'); + $view['timezones'] = $this->timezones->to_array(); + $view['working_plan_exceptions'] = '{}'; + $this->set_user_data($view); + + $this->load->view('backend/header', $view); + $this->load->view('backend/users', $view); + $this->load->view('backend/footer', $view); + } + + /** + * Display the user/system settings. + * + * This page will display the user settings (name, password etc). If current user is an administrator, then he will + * be able to make change to the current Easy!Appointment installation (core settings like company name, book + * timeout etc). + */ + public function settings() + { + $this->session->set_userdata('dest_url', site_url('backend/settings')); + if ( ! $this->has_privileges(PRIV_SYSTEM_SETTINGS, FALSE) + && ! $this->has_privileges(PRIV_USER_SETTINGS)) + { + return; + } + + $this->load->model('settings_model'); + $this->load->model('user_model'); + $this->load->library('timezones'); + + $this->load->library('session'); + $user_id = $this->session->userdata('user_id'); + + $view['base_url'] = $this->config->item('base_url'); + $view['page_title'] = lang('settings'); + $view['user_display_name'] = $this->user_model->get_user_display_name($user_id); + $view['active_menu'] = PRIV_SYSTEM_SETTINGS; + $view['company_name'] = $this->settings_model->get_setting('company_name'); + $view['date_format'] = $this->settings_model->get_setting('date_format'); + $view['first_weekday'] = $this->settings_model->get_setting('first_weekday'); + $view['time_format'] = $this->settings_model->get_setting('time_format'); + $view['role_slug'] = $this->session->userdata('role_slug'); + $view['system_settings'] = $this->settings_model->get_settings(); + $view['user_settings'] = $this->user_model->get_user($user_id); + $view['timezones'] = $this->timezones->to_array(); + + // book_advance_timeout preview + $book_advance_timeout = $this->settings_model->get_setting('book_advance_timeout'); + $hours = floor($book_advance_timeout / 60); + $minutes = $book_advance_timeout % 60; + $view['book_advance_timeout_preview'] = sprintf('%02d:%02d', $hours, $minutes); + + $this->set_user_data($view); + + $this->load->view('backend/header', $view); + $this->load->view('backend/settings', $view); + $this->load->view('backend/footer', $view); + } + + /** + * This method will update the installation to the latest available version in the server. + * + * IMPORTANT: The code files must exist in the server, this method will not fetch any new files but will update + * the database schema. + * + * This method can be used either by loading the page in the browser or by an ajax request. But it will answer with + * JSON encoded data. + */ + public function update() + { + try + { + if ( ! $this->has_privileges(PRIV_SYSTEM_SETTINGS, TRUE)) + { + throw new Exception('You do not have the required privileges for this task!'); + } + + $this->load->library('migration'); + + if ( ! $this->migration->current()) + { + throw new Exception($this->migration->error_string()); + } + + $view = ['success' => TRUE]; + } + catch (Exception $exception) + { + $view = ['success' => FALSE, 'exception' => $exception->getMessage()]; + } + + $this->load->view('general/update', $view); + } +} diff --git a/application/controllers/Backend_api.php b/application/controllers/Backend_api.php new file mode 100755 index 00000000..eb34d50f --- /dev/null +++ b/application/controllers/Backend_api.php @@ -0,0 +1,1919 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +use EA\Engine\Notifications\Email as EmailClient; +use EA\Engine\Types\Email; +use EA\Engine\Types\Text; +use EA\Engine\Types\Url; + +/** + * Backend API Controller + * + * Contains all the backend AJAX callbacks. + * + * @property CI_Session $session + * @property CI_Loader $load + * @property CI_Input $input + * @property CI_Output $output + * @property CI_Config $config + * @property CI_Lang $lang + * @property CI_Cache $cache + * @property CI_DB_query_builder $db + * @property CI_Security $security + * @property Google_Sync $google_sync + * @property Ics_file $ics_file + * @property Appointments_Model $appointments_model + * @property Providers_Model $providers_model + * @property Services_Model $services_model + * @property Customers_Model $customers_model + * @property Settings_Model $settings_model + * @property Timezones $timezones + * @property Roles_Model $roles_model + * @property Secretaries_Model $secretaries_model + * @property Admins_Model $admins_model + * @property User_Model $user_model + * + * @package Controllers + */ +class Backend_api extends CI_Controller { + /** + * @var array + */ + protected $privileges; + + /** + * Class Constructor + */ + public function __construct() + { + parent::__construct(); + + $this->load->library('session'); + $this->load->model('roles_model'); + + if ($this->session->userdata('role_slug')) + { + $this->privileges = $this->roles_model->get_privileges($this->session->userdata('role_slug')); + } + + // Set user's selected language. + if ($this->session->userdata('language')) + { + $this->config->set_item('language', $this->session->userdata('language')); + $this->lang->load('translations', $this->session->userdata('language')); + } + else + { + $this->lang->load('translations', $this->config->item('language')); // default + } + } + + /** + * Get Calendar Events + * + * This method will return all the calendar events within a specified period. + */ + public function ajax_get_calendar_events() + { + try + { + $this->output->set_content_type('application/json'); + $this->load->model('appointments_model'); + $this->load->model('customers_model'); + $this->load->model('services_model'); + $this->load->model('providers_model'); + + $startDate = $this->input->post('startDate') . ' 00:00:00'; + $endDate = $this->input->post('endDate') . ' 23:59:59'; + + $response = [ + 'appointments' => $this->appointments_model->get_batch([ + 'is_unavailable' => FALSE, + 'start_datetime >=' => $startDate, + 'end_datetime <=' => $endDate + ]), + 'unavailabilities' => $this->appointments_model->get_batch([ + 'is_unavailable' => TRUE, + 'start_datetime >=' => $startDate, + 'end_datetime <=' => $endDate + ]) + ]; + + foreach ($response['appointments'] as &$appointment) + { + $appointment['provider'] = $this->providers_model->get_row($appointment['id_users_provider']); + $appointment['service'] = $this->services_model->get_row($appointment['id_services']); + $appointment['customer'] = $this->customers_model->get_row($appointment['id_users_customer']); + } + + $userId = $this->session->userdata('user_id'); + $roleSlug = $this->session->userdata('role_slug'); + + // If the current user is a provider he must only see his own appointments. + if ($roleSlug === DB_SLUG_PROVIDER) + { + foreach ($response['appointments'] as $index => $appointment) + { + if ((int)$appointment['id_users_provider'] !== (int)$userId) + { + unset($response['appointments'][$index]); + } + } + + foreach ($response['unavailabilities'] as $index => $unavailability) + { + if ((int)$unavailability['id_users_provider'] !== (int)$userId) + { + unset($response['unavailabilities'][$index]); + } + } + } + + // If the current user is a secretary he must only see the appointments of his providers. + if ($roleSlug === DB_SLUG_SECRETARY) + { + $this->load->model('secretaries_model'); + $providers = $this->secretaries_model->get_row($userId)['providers']; + foreach ($response['appointments'] as $index => $appointment) + { + if ( ! in_array((int)$appointment['id_users_provider'], $providers)) + { + unset($response['appointments'][$index]); + } + } + + foreach ($response['unavailabilities'] as $index => $unavailability) + { + if ( ! in_array((int)$unavailability['id_users_provider'], $providers)) + { + unset($response['unavailabilities'][$index]); + } + } + } + + $this->output->set_output(json_encode($response)); + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Get the registered appointments for the given date period and record. + * + * This method returns the database appointments and unavailable periods for the + * user selected date period and record type (provider or service). + */ + public function ajax_get_calendar_appointments() + { + try + { + if ($this->privileges[PRIV_APPOINTMENTS]['view'] == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + if ( ! $this->input->post('filter_type')) + { + $this->output + ->set_content_type('application/json') + ->set_output(json_encode(['appointments' => []])); + return; + } + + $this->load->model('appointments_model'); + $this->load->model('providers_model'); + $this->load->model('services_model'); + $this->load->model('customers_model'); + + if ($this->input->post('filter_type') == FILTER_TYPE_PROVIDER) + { + $where_id = 'id_users_provider'; + } + else + { + $where_id = 'id_services'; + } + + // Get appointments + $record_id = $this->db->escape($this->input->post('record_id')); + $start_date = $this->db->escape($this->input->post('start_date')); + $end_date = $this->db->escape(date('Y-m-d', strtotime($this->input->post('end_date') . ' +1 day'))); + + $where_clause = $where_id . ' = ' . $record_id . ' + AND ((start_datetime > ' . $start_date . ' AND start_datetime < ' . $end_date . ') + or (end_datetime > ' . $start_date . ' AND end_datetime < ' . $end_date . ') + or (start_datetime <= ' . $start_date . ' AND end_datetime >= ' . $end_date . ')) + AND is_unavailable = 0 + '; + + $response['appointments'] = $this->appointments_model->get_batch($where_clause); + + foreach ($response['appointments'] as &$appointment) + { + $appointment['provider'] = $this->providers_model->get_row($appointment['id_users_provider']); + $appointment['service'] = $this->services_model->get_row($appointment['id_services']); + $appointment['customer'] = $this->customers_model->get_row($appointment['id_users_customer']); + } + + // Get unavailable periods (only for provider). + if ($this->input->post('filter_type') == FILTER_TYPE_PROVIDER) + { + $where_clause = $where_id . ' = ' . $record_id . ' + AND ((start_datetime > ' . $start_date . ' AND start_datetime < ' . $end_date . ') + or (end_datetime > ' . $start_date . ' AND end_datetime < ' . $end_date . ') + or (start_datetime <= ' . $start_date . ' AND end_datetime >= ' . $end_date . ')) + AND is_unavailable = 1 + '; + + $response['unavailables'] = $this->appointments_model->get_batch($where_clause); + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Save appointment changes that are made from the backend calendar page. + */ + public function ajax_save_appointment() + { + try + { + $this->load->model('appointments_model'); + $this->load->model('providers_model'); + $this->load->model('admins_model'); + $this->load->model('secretaries_model'); + $this->load->model('services_model'); + $this->load->model('customers_model'); + $this->load->model('settings_model'); + $this->load->library('timezones'); + $this->load->model('user_model'); + + // Save customer changes to the database. + if ($this->input->post('customer_data')) + { + $customer = json_decode($this->input->post('customer_data'), TRUE); + + $required_privilegesileges = ( ! isset($customer['id'])) + ? $this->privileges[PRIV_CUSTOMERS]['add'] + : $this->privileges[PRIV_CUSTOMERS]['edit']; + if ($required_privilegesileges == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $customer['id'] = $this->customers_model->add($customer); + } + + // Save appointment changes to the database. + if ($this->input->post('appointment_data')) + { + $appointment = json_decode($this->input->post('appointment_data'), TRUE); + + $required_privilegesileges = ( ! isset($appointment['id'])) + ? $this->privileges[PRIV_APPOINTMENTS]['add'] + : $this->privileges[PRIV_APPOINTMENTS]['edit']; + if ($required_privilegesileges == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $manage_mode = isset($appointment['id']); + // If the appointment does not contain the customer record id, then it + // means that is is going to be inserted. Get the customer's record id. + if ( ! isset($appointment['id_users_customer'])) + { + $appointment['id_users_customer'] = $customer['id']; + } + + $provider_timezone = $this->user_model->get_user_timezone($appointment['id_users_provider']); + + $session_timezone = $this->timezones->get_session_timezone(); + + $appointment['start_datetime'] = $this->timezones->convert($appointment['start_datetime'], + $session_timezone, $provider_timezone); + + $appointment['end_datetime'] = $this->timezones->convert($appointment['end_datetime'], + $session_timezone, $provider_timezone); + + $appointment['id'] = $this->appointments_model->add($appointment); + } + + $appointment = $this->appointments_model->get_row($appointment['id']); + $provider = $this->providers_model->get_row($appointment['id_users_provider']); + $customer = $this->customers_model->get_row($appointment['id_users_customer']); + $service = $this->services_model->get_row($appointment['id_services']); + + $settings = [ + 'company_name' => $this->settings_model->get_setting('company_name'), + 'company_link' => $this->settings_model->get_setting('company_link'), + 'company_email' => $this->settings_model->get_setting('company_email'), + 'date_format' => $this->settings_model->get_setting('date_format'), + 'time_format' => $this->settings_model->get_setting('time_format') + ]; + + // Sync appointment changes with Google Calendar. + try + { + $google_sync = $this->providers_model->get_setting('google_sync', + $appointment['id_users_provider']); + + if ($google_sync == TRUE) + { + $google_token = json_decode($this->providers_model->get_setting('google_token', + $appointment['id_users_provider'])); + + $this->load->library('Google_sync'); + $this->google_sync->refresh_token($google_token->refresh_token); + + if ($appointment['id_google_calendar'] == NULL) + { + $google_event = $this->google_sync->add_appointment($appointment, $provider, + $service, $customer, $settings); + $appointment['id_google_calendar'] = $google_event->id; + $this->appointments_model->add($appointment); // Store google calendar id. + } + else + { + $this->google_sync->update_appointment($appointment, $provider, + $service, $customer, $settings); + } + } + } + catch (Exception $exception) + { + $warnings[] = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + // Send email notifications to provider and customer. + try + { + $this->config->load('email'); + $email = new EmailClient($this, $this->config->config); + + $send_provider = $this->providers_model + ->get_setting('notifications', $provider['id']); + + if ( ! $manage_mode) + { + $customer_title = new Text(lang('appointment_booked')); + $customer_message = new Text(lang('thank_you_for_appointment')); + $provider_title = new Text(lang('appointment_added_to_your_plan')); + $provider_message = new Text(lang('appointment_link_description')); + } + else + { + $customer_title = new Text(lang('appointment_details_changed')); + $customer_message = new Text(''); + $provider_title = new Text(lang('appointment_changes_saved')); + $provider_message = new Text(''); + } + + $customer_link = new Url(site_url('appointments/index/' . $appointment['hash'])); + $provider_link = new Url(site_url('backend/index/' . $appointment['hash'])); + + $send_customer = $this->settings_model->get_setting('customer_notifications'); + + $this->load->library('ics_file'); + $ics_stream = $this->ics_file->get_stream($appointment, $service, $provider, $customer); + + if ((bool)$send_customer === TRUE) + { + $email->sendAppointmentDetails($appointment, $provider, + $service, $customer, $settings, $customer_title, + $customer_message, $customer_link, new Email($customer['email']), new Text($ics_stream)); + } + + if ($send_provider == TRUE) + { + $email->sendAppointmentDetails($appointment, $provider, + $service, $customer, $settings, $provider_title, + $provider_message, $provider_link, new Email($provider['email']), new Text($ics_stream)); + } + + // Notify admins + $admins = $this->admins_model->get_batch(); + + foreach($admins as $admin) + { + if (!$admin['settings']['notifications'] === '0') + { + continue; + } + + $email->sendAppointmentDetails($appointment, $provider, + $service, $customer, $settings, $provider_title, + $provider_message, $provider_link, new Email($admin['email']), new Text($ics_stream)); + } + + // Notify secretaries + $secretaries = $this->secretaries_model->get_batch(); + + foreach($secretaries as $secretary) + { + if (!$secretary['settings']['notifications'] === '0') + { + continue; + } + + if (in_array($provider['id'], $secretary['providers'])) + { + continue; + } + + $email->sendAppointmentDetails($appointment, $provider, + $service, $customer, $settings, $provider_title, + $provider_message, $provider_link, new Email($secretary['email']), new Text($ics_stream)); + } + } + catch (Exception $exception) + { + $warnings[] = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + if (empty($warnings)) + { + $response = AJAX_SUCCESS; + } + else + { + $response = ['warnings' => $warnings]; + } + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Delete appointment from the database. + * + * This method deletes an existing appointment from the database. Once this action is finished it cannot be undone. + * Notification emails are send to both provider and customer and the delete action is executed to the Google + * Calendar account of the provider, if the "google_sync" setting is enabled. + */ + public function ajax_delete_appointment() + { + try + { + if ($this->privileges[PRIV_APPOINTMENTS]['delete'] == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + if ( ! $this->input->post('appointment_id')) + { + throw new Exception('No appointment id provided.'); + } + + // Store appointment data for later use in this method. + $this->load->model('appointments_model'); + $this->load->model('providers_model'); + $this->load->model('admins_model'); + $this->load->model('secretaries_model'); + $this->load->model('customers_model'); + $this->load->model('services_model'); + $this->load->model('settings_model'); + + $appointment = $this->appointments_model->get_row($this->input->post('appointment_id')); + $provider = $this->providers_model->get_row($appointment['id_users_provider']); + $customer = $this->customers_model->get_row($appointment['id_users_customer']); + $service = $this->services_model->get_row($appointment['id_services']); + + $settings = [ + 'company_name' => $this->settings_model->get_setting('company_name'), + 'company_email' => $this->settings_model->get_setting('company_email'), + 'company_link' => $this->settings_model->get_setting('company_link'), + 'date_format' => $this->settings_model->get_setting('date_format'), + 'time_format' => $this->settings_model->get_setting('time_format') + ]; + + // Delete appointment record from the database. + $this->appointments_model->delete($this->input->post('appointment_id')); + + // Sync removal with Google Calendar. + if ($appointment['id_google_calendar'] != NULL) + { + try + { + $google_sync = $this->providers_model->get_setting('google_sync', $provider['id']); + + if ($google_sync == TRUE) + { + $google_token = json_decode($this->providers_model + ->get_setting('google_token', $provider['id'])); + $this->load->library('Google_sync'); + $this->google_sync->refresh_token($google_token->refresh_token); + $this->google_sync->delete_appointment($provider, $appointment['id_google_calendar']); + } + } + catch (Exception $exception) + { + $warnings[] = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + } + + // Send notification emails to provider and customer. + try + { + $this->config->load('email'); + + $email = new EmailClient($this, $this->config->config); + + $send_provider = $this->providers_model + ->get_setting('notifications', $provider['id']); + + if ((bool)$send_provider === TRUE) + { + $email->sendDeleteAppointment($appointment, $provider, + $service, $customer, $settings, new Email($provider['email']), + new Text($this->input->post('delete_reason'))); + } + + $send_customer = $this->settings_model->get_setting('customer_notifications'); + + if ((bool)$send_customer === TRUE) + { + $email->sendDeleteAppointment($appointment, $provider, + $service, $customer, $settings, new Email($customer['email']), + new Text($this->input->post('delete_reason'))); + } + + // Notify admins + $admins = $this->admins_model->get_batch(); + + foreach($admins as $admin) + { + if (!$admin['settings']['notifications'] === '0') + { + continue; + } + + $email->sendDeleteAppointment($appointment, $provider, + $service, $customer, $settings, new Email($admin['email']), + new Text($this->input->post('cancel_reason'))); + } + + // Notify secretaries + $secretaries = $this->secretaries_model->get_batch(); + + foreach($secretaries as $secretary) + { + if (!$secretary['settings']['notifications'] === '0') + { + continue; + } + + if (in_array($provider['id'], $secretary['providers'])) + { + continue; + } + + $email->sendDeleteAppointment($appointment, $provider, + $service, $customer, $settings, new Email($secretary['email']), + new Text($this->input->post('cancel_reason'))); + } + } + catch (Exception $exception) + { + $warnings[] = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + if (empty($warnings)) + { + $response = AJAX_SUCCESS; + } + else + { + $response = ['warnings' => $warnings]; + } + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Disable a providers sync setting. + * + * This method deletes the "google_sync" and "google_token" settings from the database. After that the provider's + * appointments will be no longer synced with google calendar. + */ + public function ajax_disable_provider_sync() + { + try + { + if ( ! $this->input->post('provider_id')) + { + throw new Exception('Provider id not specified.'); + } + + if ($this->privileges[PRIV_USERS]['edit'] == FALSE + && $this->session->userdata('user_id') != $this->input->post('provider_id')) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $this->load->model('providers_model'); + $this->load->model('appointments_model'); + $this->providers_model->set_setting('google_sync', FALSE, $this->input->post('provider_id')); + $this->providers_model->set_setting('google_token', NULL, $this->input->post('provider_id')); + $this->appointments_model->clear_google_sync_ids($this->input->post('provider_id')); + + $response = AJAX_SUCCESS; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Filter the customer records with the given key string. + * + * Outputs the search results. + */ + public function ajax_filter_customers() + { + try + { + if ($this->privileges[PRIV_CUSTOMERS]['view'] == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $this->load->model('appointments_model'); + $this->load->model('services_model'); + $this->load->model('providers_model'); + $this->load->model('customers_model'); + + $key = $this->db->escape_str($this->input->post('key')); + $key = strtoupper($key); + + $where = + '(first_name LIKE upper("%' . $key . '%") OR ' . + 'last_name LIKE upper("%' . $key . '%") OR ' . + 'email LIKE upper("%' . $key . '%") OR ' . + 'phone_number LIKE upper("%' . $key . '%") OR ' . + 'address LIKE upper("%' . $key . '%") OR ' . + 'city LIKE upper("%' . $key . '%") OR ' . + 'zip_code LIKE upper("%' . $key . '%") OR ' . + 'notes LIKE upper("%' . $key . '%"))'; + + $order_by = 'first_name ASC, last_name ASC'; + + $limit = $this->input->post('limit'); + + if ($limit === NULL) + { + $limit = 1000; + } + + $customers = $this->customers_model->get_batch($where, $order_by, $limit); + + foreach ($customers as &$customer) + { + $appointments = $this->appointments_model + ->get_batch(['id_users_customer' => $customer['id']]); + + foreach ($appointments as &$appointment) + { + $appointment['service'] = $this->services_model->get_row($appointment['id_services']); + $appointment['provider'] = $this->providers_model->get_row($appointment['id_users_provider']); + } + + $customer['appointments'] = $appointments; + } + + $response = $customers; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Insert of update unavailable time period to database. + */ + public function ajax_save_unavailable() + { + try + { + // Check privileges + $unavailable = json_decode($this->input->post('unavailable'), TRUE); + + $required_privileges = ( ! isset($unavailable['id'])) + ? $this->privileges[PRIV_APPOINTMENTS]['add'] + : $this->privileges[PRIV_APPOINTMENTS]['edit']; + if ($required_privileges == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $this->load->model('appointments_model'); + $this->load->model('providers_model'); + + $provider = $this->providers_model->get_row($unavailable['id_users_provider']); + + // Add appointment + $unavailable['id'] = $this->appointments_model->add_unavailable($unavailable); + $unavailable = $this->appointments_model->get_row($unavailable['id']); // fetch all inserted data + + // Google Sync + try + { + $google_sync = $this->providers_model->get_setting('google_sync', + $unavailable['id_users_provider']); + + if ($google_sync) + { + $google_token = json_decode($this->providers_model->get_setting('google_token', + $unavailable['id_users_provider'])); + + $this->load->library('google_sync'); + $this->google_sync->refresh_token($google_token->refresh_token); + + if ($unavailable['id_google_calendar'] == NULL) + { + $google_event = $this->google_sync->add_unavailable($provider, $unavailable); + $unavailable['id_google_calendar'] = $google_event->id; + $this->appointments_model->add_unavailable($unavailable); + } + else + { + $this->google_sync->update_unavailable($provider, $unavailable); + } + } + } + catch (Exception $exception) + { + $warnings[] = $exception; + } + + if (isset($warnings)) + { + $this->output + ->set_content_type('application/json') + ->set_output(json_encode(['warnings' => $warnings])); + } + else + { + $this->output + ->set_content_type('application/json') + ->set_output(json_encode(AJAX_SUCCESS)); + } + + $response = AJAX_SUCCESS; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Delete an unavailable time period from database. + */ + public function ajax_delete_unavailable() + { + try + { + if ($this->privileges[PRIV_APPOINTMENTS]['delete'] == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $this->load->model('appointments_model'); + $this->load->model('providers_model'); + + $unavailable = $this->appointments_model->get_row($this->input->post('unavailable_id')); + $provider = $this->providers_model->get_row($unavailable['id_users_provider']); + + // Delete unavailable + $this->appointments_model->delete_unavailable($unavailable['id']); + + // Google Sync + try + { + $google_sync = $this->providers_model->get_setting('google_sync', $provider['id']); + if ($google_sync == TRUE) + { + $google_token = json_decode($this->providers_model->get_setting('google_token', $provider['id'])); + $this->load->library('google_sync'); + $this->google_sync->refresh_token($google_token->refresh_token); + $this->google_sync->delete_unavailable($provider, $unavailable['id_google_calendar']); + } + } + catch (Exception $exception) + { + $warnings[] = $exception; + } + + if (empty($warnings)) + { + $response = AJAX_SUCCESS; + } + else + { + $response = ['warnings' => $warnings]; + } + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Insert of update working plan exceptions to database. + */ + public function ajax_save_working_plan_exception() + { + try + { + // Check privileges + $required_privileges = $this->privileges[PRIV_USERS]['edit']; + + if ($required_privileges == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $date = $this->input->post('date'); + $working_plan_exception = $this->input->post('working_plan_exception'); + $provider_id = $this->input->post('provider_id'); + + $this->load->model('providers_model'); + + $success = $this->providers_model->save_working_plan_exception($date, $working_plan_exception, $provider_id); + + if ($success) + { + $response = AJAX_SUCCESS; + } + else + { + $response = ['warnings' => 'Error on saving working plan exception.']; + } + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Delete an working plan exceptions time period to database. + */ + public function ajax_delete_working_plan_exception() + { + try + { + // Check privileges + $required_privileges = $this->privileges[PRIV_USERS]['edit']; + + if ($required_privileges == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $date = $this->input->post('date'); + $provider_id = $this->input->post('provider_id'); + + $this->load->model('providers_model'); + + $success = $this->providers_model->delete_working_plan_exception($date, $provider_id); + + if ($success) + { + $response = AJAX_SUCCESS; + } + else + { + $response = ['warnings' => 'Error on deleting working plan exception.']; + } + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Save (insert or update) a customer record. + */ + public function ajax_save_customer() + { + try + { + $this->load->model('customers_model'); + $customer = json_decode($this->input->post('customer'), TRUE); + + $required_privilegesileges = ( ! isset($customer['id'])) + ? $this->privileges[PRIV_CUSTOMERS]['add'] + : $this->privileges[PRIV_CUSTOMERS]['edit']; + if ($required_privilegesileges == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $customer_id = $this->customers_model->add($customer); + + $response = [ + 'status' => AJAX_SUCCESS, + 'id' => $customer_id + ]; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Delete customer from database. + */ + public function ajax_delete_customer() + { + try + { + if ($this->privileges[PRIV_CUSTOMERS]['delete'] == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $this->load->model('customers_model'); + + $this->customers_model->delete($this->input->post('customer_id')); + + $response = AJAX_SUCCESS; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Save (insert or update) service record. + */ + public function ajax_save_service() + { + try + { + $this->load->model('services_model'); + $service = json_decode($this->input->post('service'), TRUE); + + $required_privilegesileges = ( ! isset($service['id'])) + ? $this->privileges[PRIV_SERVICES]['add'] + : $this->privileges[PRIV_SERVICES]['edit']; + if ($required_privilegesileges == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $service_id = $this->services_model->add($service); + $response = [ + 'status' => AJAX_SUCCESS, + 'id' => $service_id + ]; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Delete service record from database. + */ + public function ajax_delete_service() + { + try + { + if ($this->privileges[PRIV_SERVICES]['delete'] == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $this->load->model('services_model'); + + $result = $this->services_model->delete($this->input->post('service_id')); + + $response = $result ? AJAX_SUCCESS : AJAX_FAILURE; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Filter service records by given key string. + */ + public function ajax_filter_services() + { + try + { + if ($this->privileges[PRIV_SERVICES]['view'] == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $this->load->model('services_model'); + + $key = $this->db->escape_str($this->input->post('key')); + + $where = + '(name LIKE "%' . $key . '%" OR duration LIKE "%' . $key . '%" OR ' . + 'price LIKE "%' . $key . '%" OR currency LIKE "%' . $key . '%" OR ' . + 'description LIKE "%' . $key . '%")'; + + $response = $this->services_model->get_batch($where); + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Save (insert or update) category record. + */ + public function ajax_save_service_category() + { + try + { + $this->load->model('services_model'); + $category = json_decode($this->input->post('category'), TRUE); + + $required_privilegesileges = ( ! isset($category['id'])) + ? $this->privileges[PRIV_SERVICES]['add'] + : $this->privileges[PRIV_SERVICES]['edit']; + if ($required_privilegesileges == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $category_id = $this->services_model->add_category($category); + + $response = [ + 'status' => AJAX_SUCCESS, + 'id' => $category_id + ]; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Delete category record from database. + */ + public function ajax_delete_service_category() + { + try + { + if ($this->privileges[PRIV_SERVICES]['delete'] == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $this->load->model('services_model'); + + $result = $this->services_model->delete_category($this->input->post('category_id')); + + $response = $result ? AJAX_SUCCESS : AJAX_FAILURE; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Filter services categories with key string. + */ + public function ajax_filter_service_categories() + { + try + { + if ($this->privileges[PRIV_SERVICES]['view'] == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $this->load->model('services_model'); + + $key = $this->db->escape_str($this->input->post('key')); + + $where = '(name LIKE "%' . $key . '%" OR description LIKE "%' . $key . '%")'; + + $response = $this->services_model->get_all_categories($where); + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Filter admin records with string key. + */ + public function ajax_filter_admins() + { + try + { + if ($this->privileges[PRIV_USERS]['view'] == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $this->load->model('admins_model'); + + $key = $this->db->escape_str($this->input->post('key')); + + $where = + '(first_name LIKE "%' . $key . '%" OR last_name LIKE "%' . $key . '%" ' . + 'OR email LIKE "%' . $key . '%" OR mobile_number LIKE "%' . $key . '%" ' . + 'OR phone_number LIKE "%' . $key . '%" OR address LIKE "%' . $key . '%" ' . + 'OR city LIKE "%' . $key . '%" OR state LIKE "%' . $key . '%" ' . + 'OR zip_code LIKE "%' . $key . '%" OR notes LIKE "%' . $key . '%")'; + + $response = $this->admins_model->get_batch($where); + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Save (insert or update) admin record into database. + */ + public function ajax_save_admin() + { + try + { + $this->load->model('admins_model'); + $admin = json_decode($this->input->post('admin'), TRUE); + + $required_privileges = ( ! isset($admin['id'])) + ? $this->privileges[PRIV_USERS]['add'] + : $this->privileges[PRIV_USERS]['edit']; + if ($required_privileges == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $admin_id = $this->admins_model->add($admin); + + $response = [ + 'status' => AJAX_SUCCESS, + 'id' => $admin_id + ]; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Delete an admin record from the database. + */ + public function ajax_delete_admin() + { + try + { + if ($this->privileges[PRIV_USERS]['delete'] == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $this->load->model('admins_model'); + + $result = $this->admins_model->delete($this->input->post('admin_id')); + + $response = $result ? AJAX_SUCCESS : AJAX_FAILURE; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Filter provider records with string key. + */ + public function ajax_filter_providers() + { + try + { + if ($this->privileges[PRIV_USERS]['view'] == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $this->load->model('providers_model'); + + $key = $this->db->escape_str($this->input->post('key')); + + $where = + '(first_name LIKE "%' . $key . '%" OR last_name LIKE "%' . $key . '%" ' . + 'OR email LIKE "%' . $key . '%" OR mobile_number LIKE "%' . $key . '%" ' . + 'OR phone_number LIKE "%' . $key . '%" OR address LIKE "%' . $key . '%" ' . + 'OR city LIKE "%' . $key . '%" OR state LIKE "%' . $key . '%" ' . + 'OR zip_code LIKE "%' . $key . '%" OR notes LIKE "%' . $key . '%")'; + + $response = $this->providers_model->get_batch($where); + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Save (insert or update) a provider record into database. + */ + public function ajax_save_provider() + { + try + { + $this->load->model('providers_model'); + $provider = json_decode($this->input->post('provider'), TRUE); + + $required_privileges = ( ! isset($provider['id'])) + ? $this->privileges[PRIV_USERS]['add'] + : $this->privileges[PRIV_USERS]['edit']; + if ($required_privileges == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + if ( ! isset($provider['settings']['working_plan'])) + { + $this->load->model('settings_model'); + $provider['settings']['working_plan'] = $this->settings_model + ->get_setting('company_working_plan'); + } + + $provider_id = $this->providers_model->add($provider); + + $response = [ + 'status' => AJAX_SUCCESS, + 'id' => $provider_id + ]; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Delete a provider record from the database. + */ + public function ajax_delete_provider() + { + try + { + if ($this->privileges[PRIV_USERS]['delete'] == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $this->load->model('providers_model'); + + $result = $this->providers_model->delete($this->input->post('provider_id')); + + $response =$result ? AJAX_SUCCESS : AJAX_FAILURE; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Filter secretary records with string key. + */ + public function ajax_filter_secretaries() + { + try + { + if ($this->privileges[PRIV_USERS]['view'] == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $this->load->model('secretaries_model'); + + $key = $this->db->escape_str($this->input->post('key')); + + $where = + '(first_name LIKE "%' . $key . '%" OR last_name LIKE "%' . $key . '%" ' . + 'OR email LIKE "%' . $key . '%" OR mobile_number LIKE "%' . $key . '%" ' . + 'OR phone_number LIKE "%' . $key . '%" OR address LIKE "%' . $key . '%" ' . + 'OR city LIKE "%' . $key . '%" OR state LIKE "%' . $key . '%" ' . + 'OR zip_code LIKE "%' . $key . '%" OR notes LIKE "%' . $key . '%")'; + + $response = $this->secretaries_model->get_batch($where); + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Save (insert or update) a secretary record into database. + */ + public function ajax_save_secretary() + { + try + { + $this->load->model('secretaries_model'); + $secretary = json_decode($this->input->post('secretary'), TRUE); + + $required_privileges = ( ! isset($secretary['id'])) + ? $this->privileges[PRIV_USERS]['add'] + : $this->privileges[PRIV_USERS]['edit']; + if ($required_privileges == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $secretary_id = $this->secretaries_model->add($secretary); + + $response =[ + 'status' => AJAX_SUCCESS, + 'id' => $secretary_id + ]; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Delete a secretary record from the database. + */ + public function ajax_delete_secretary() + { + try + { + if ($this->privileges[PRIV_USERS]['delete'] == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $this->load->model('secretaries_model'); + + $result = $this->secretaries_model->delete($this->input->post('secretary_id')); + + $response =$result ? AJAX_SUCCESS : AJAX_FAILURE; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Save a setting or multiple settings in the database. + */ + public function ajax_save_settings() + { + try + { + if ($this->input->post('type') == SETTINGS_SYSTEM) + { + if ($this->privileges[PRIV_SYSTEM_SETTINGS]['edit'] == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $this->load->model('settings_model'); + + $settings = json_decode($this->input->post('settings', FALSE), TRUE); + + $this->settings_model->save_settings($settings); + } + else + { + if ($this->input->post('type') == SETTINGS_USER) + { + if ($this->privileges[PRIV_USER_SETTINGS]['edit'] == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $this->load->model('user_model'); + + $this->user_model->save_user(json_decode($this->input->post('settings'), TRUE)); + } + } + + $response = AJAX_SUCCESS; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * This method checks whether the username already exists in the database. + */ + public function ajax_validate_username() + { + try + { + // We will only use the function in the admins_model because it is sufficient for the rest user types for + // now (providers, secretaries). + + $this->load->model('admins_model'); + + $is_valid = $this->admins_model->validate_username($this->input->post('username'), + $this->input->post('user_id')); + + $response = $is_valid; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Change system language for current user. + * + * The language setting is stored in session data and retrieved every time the user visits any of the system pages. + */ + public function ajax_change_language() + { + try + { + // Check if language exists in the available languages. + $found = FALSE; + + foreach ($this->config->item('available_languages') as $lang) + { + if ($lang == $this->input->post('language')) + { + $found = TRUE; + break; + } + } + + if ( ! $found) + { + throw new Exception('Translations for the given language does not exist (' . $this->input->post('language') . ').'); + } + + $this->session->set_userdata('language', $this->input->post('language')); + $this->config->set_item('language', $this->input->post('language')); + + $response = AJAX_SUCCESS; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * This method will return a list of the available google calendars. + * + * The user will need to select a specific calendar from this list to sync his appointments with. Google access must + * be already granted for the specific provider. + */ + public function ajax_get_google_calendars() + { + try + { + $this->load->library('google_sync'); + $this->load->model('providers_model'); + + if ( ! $this->input->post('provider_id')) + { + throw new Exception('Provider id is required in order to fetch the google calendars.'); + } + + // Check if selected provider has sync enabled. + $google_sync = $this->providers_model->get_setting('google_sync', $this->input->post('provider_id')); + + if ($google_sync) + { + $google_token = json_decode($this->providers_model->get_setting('google_token', + $this->input->post('provider_id'))); + $this->google_sync->refresh_token($google_token->refresh_token); + + $calendars = $this->google_sync->get_google_calendars(); + + $response = $calendars; + } + else + { + $response =AJAX_FAILURE; + } + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Select a specific google calendar for a provider. + * + * All the appointments will be synced with this particular calendar. + */ + public function ajax_select_google_calendar() + { + try + { + if ($this->privileges[PRIV_USERS]['edit'] == FALSE + && $this->session->userdata('user_id') != $this->input->post('provider_id')) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $this->load->model('providers_model'); + + $result = $this->providers_model->set_setting('google_calendar', $this->input->post('calendar_id'), + $this->input->post('provider_id')); + + $response = $result ? AJAX_SUCCESS : AJAX_FAILURE; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Apply global working plan to all providers. + */ + public function ajax_apply_global_working_plan() + { + try + { + if ($this->privileges[PRIV_SYSTEM_SETTINGS]['edit'] == FALSE) + { + throw new Exception('You do not have the required privileges for this task.'); + } + + $working_plan = $this->input->post('working_plan'); + + $this->load->model('providers_model'); + + $providers = $this->providers_model->get_batch(); + + foreach ($providers as $provider) + { + $this->providers_model->set_setting('working_plan', $working_plan, $provider['id']); + } + + $response =AJAX_SUCCESS; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } +} diff --git a/application/controllers/Captcha.php b/application/controllers/Captcha.php new file mode 100644 index 00000000..897aa0fa --- /dev/null +++ b/application/controllers/Captcha.php @@ -0,0 +1,62 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +/** + * Captcha Controller + * + * @property CI_Session $session + * @property CI_Loader $load + * @property CI_Input $input + * @property CI_Output $output + * @property CI_Config $config + * @property CI_Lang $lang + * @property CI_Cache $cache + * @property CI_DB_query_builder $db + * @property CI_Security $security + * @property Google_Sync $google_sync + * @property Ics_file $ics_file + * @property Appointments_Model $appointments_model + * @property Providers_Model $providers_model + * @property Services_Model $services_model + * @property Customers_Model $customers_model + * @property Settings_Model $settings_model + * @property Timezones $timezones + * @property Roles_Model $roles_model + * @property Secretaries_Model $secretaries_model + * @property Admins_Model $admins_model + * @property User_Model $user_model + * + * @package Controllers + */ +class Captcha extends CI_Controller { + /** + * Class Constructor + */ + public function __construct() + { + parent::__construct(); + $this->load->library('session'); + } + + /** + * Make a request to this method to get a captcha image. + */ + public function index() + { + header('Content-type: image/jpeg'); + $builder = new Gregwar\Captcha\CaptchaBuilder; + $builder->build(); + $this->session->set_userdata('captcha_phrase', $builder->getPhrase()); + $builder->output(); + } +} diff --git a/application/controllers/Consents.php b/application/controllers/Consents.php new file mode 100644 index 00000000..bd8e4fb2 --- /dev/null +++ b/application/controllers/Consents.php @@ -0,0 +1,79 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.3.2 + * ---------------------------------------------------------------------------- */ + +/** + * Class Consent + * + * Handles user consent related operations. + * + * @property CI_Session $session + * @property CI_Loader $load + * @property CI_Input $input + * @property CI_Output $output + * @property CI_Config $config + * @property CI_Lang $lang + * @property CI_Cache $cache + * @property CI_DB_query_builder $db + * @property CI_Security $security + * @property Google_Sync $google_sync + * @property Ics_file $ics_file + * @property Appointments_Model $appointments_model + * @property Providers_Model $providers_model + * @property Services_Model $services_model + * @property Customers_Model $customers_model + * @property Consents_Model consents_model + * @property Settings_Model $settings_model + * @property Timezones $timezones + * @property Roles_Model $roles_model + * @property Secretaries_Model $secretaries_model + * @property Admins_Model $admins_model + * @property User_Model $user_model + * + * @package Controllers + */ +class Consents extends CI_Controller { + /** + * Save the user's consent. + */ + public function ajax_save_consent() + { + try + { + $this->load->model('consents_model'); + + $consent = $this->input->post('consent'); + + $consent['ip'] = $this->input->ip_address(); + + $consent['id'] = $this->consents_model->add($consent); + + $response = [ + 'success' => TRUE, + 'id' => $consent['id'] + ]; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } +} diff --git a/application/controllers/Console.php b/application/controllers/Console.php new file mode 100644 index 00000000..afea3f9c --- /dev/null +++ b/application/controllers/Console.php @@ -0,0 +1,90 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.3.2 + * ---------------------------------------------------------------------------- */ + +require_once __DIR__ .'/Google.php'; + +/** + * Class Console + * + * CLI commands of Easy!Appointments, can only be executed from a terminal and not with a direct request. + * + * @property CI_Migration $migration + * @property Providers_model $providers_model + */ +class Console extends CI_Controller { + /** + * Console constructor. + */ + public function __construct() + { + if ( ! is_cli()) + { + exit('No direct script access allowed'); + } + + parent::__construct(); + + $this->load->library('migration'); + $this->load->model('providers_model'); + } + + /** + * Migrate the database to the latest state. + * + * Use this method to upgrade an existing installation to the latest database state. + * + * Notice: + * + * Do not use this method to install the app as it will not seed the database with the initial entries (admin, + * provider, service, settings etc). Use the UI installation page for this. + * + * Usage: + * + * php index.php console migrate + */ + public function migrate() + { + if ($this->migration->current() === FALSE) + { + show_error($this->migration->error_string()); + } + } + + /** + * Trigger the synchronization of all provider calendars with Google Calendar. + * + * Use this method in a cronjob to automatically sync events between Easy!Appointments and Google Calendar. + * + * Notice: + * + * Google syncing must first be enabled for each individual provider from inside the backend calendar page. + * + * Usage: + * + * php index.php console sync + */ + public function sync() + { + $providers = $this->providers_model->get_batch(); + + foreach ($providers as $provider) + { + if ( ! filter_var($provider['settings']['google_sync'], FILTER_VALIDATE_BOOLEAN)) + { + continue; + } + + Google::sync($provider['id']); + } + } +} diff --git a/application/controllers/Errors.php b/application/controllers/Errors.php new file mode 100644 index 00000000..425a35ed --- /dev/null +++ b/application/controllers/Errors.php @@ -0,0 +1,84 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +/** + * Errors Controller + * + * @property CI_Session $session + * @property CI_Loader $load + * @property CI_Input $input + * @property CI_Output $output + * @property CI_Config $config + * @property CI_Lang $lang + * @property CI_Cache $cache + * @property CI_DB_query_builder $db + * @property CI_Security $security + * @property Google_Sync $google_sync + * @property Ics_file $ics_file + * @property Appointments_Model $appointments_model + * @property Providers_Model $providers_model + * @property Services_Model $services_model + * @property Customers_Model $customers_model + * @property Settings_Model $settings_model + * @property Timezones $timezones + * @property Roles_Model $roles_model + * @property Secretaries_Model $secretaries_model + * @property Admins_Model $admins_model + * @property User_Model $user_model + * + * @package Controllers + */ +class Errors extends CI_Controller { + /** + * Class Constructor + */ + public function __construct() + { + parent::__construct(); + + $this->load->library('session'); + + if ($this->session->userdata('language')) + { + // Set user's selected language. + $this->config->set_item('language', $this->session->userdata('language')); + $this->lang->load('translations', $this->session->userdata('language')); + } + else + { + // Set the default language. + $this->lang->load('translations', $this->config->item('language')); + } + } + + /** + * Display the 404 error page. + */ + public function index() + { + $this->error404(); + } + + /** + * Display the 404 error page. + */ + public function error404() + { + $this->load->helper('google_analytics'); + $this->load->model('settings_model'); + + $view['company_name'] = $this->settings_model->get_setting('company_name'); + + $this->load->view('general/error404', $view); + } +} diff --git a/application/controllers/Google.php b/application/controllers/Google.php new file mode 100644 index 00000000..455d8908 --- /dev/null +++ b/application/controllers/Google.php @@ -0,0 +1,320 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +/** + * Google Controller + * + * This controller handles the Google Calendar synchronization operations. + * + * @property CI_Session $session + * @property CI_Loader $load + * @property CI_Input $input + * @property CI_Output $output + * @property CI_Config $config + * @property CI_Lang $lang + * @property CI_Cache $cache + * @property CI_DB_query_builder $db + * @property CI_Security $security + * @property Google_Sync $google_sync + * @property Ics_file $ics_file + * @property Appointments_Model $appointments_model + * @property Providers_Model $providers_model + * @property Services_Model $services_model + * @property Customers_Model $customers_model + * @property Settings_Model $settings_model + * @property Timezones $timezones + * @property Roles_Model $roles_model + * @property Secretaries_Model $secretaries_model + * @property Admins_Model $admins_model + * @property User_Model $user_model + * + * @package Controllers + */ +class Google extends CI_Controller { + /** + * Class Constructor + */ + public function __construct() + { + parent::__construct(); + + $this->load->library('session'); + } + + /** + * Authorize Google Calendar API usage for a specific provider. + * + * Since it is required to follow the web application flow, in order to retrieve a refresh token from the Google API + * service, this method is going to authorize the given provider. + * + * @param int $provider_id The provider id, for whom the sync authorization is made. + */ + public function oauth($provider_id) + { + // Store the provider id for use on the callback function. + $this->session->set_userdata('oauth_provider_id', $provider_id); + + // Redirect browser to google user content page. + $this->load->library('google_sync'); + header('Location: ' . $this->google_sync->get_auth_url()); + } + + /** + * Callback method for the Google Calendar API authorization process. + * + * Once the user grants consent with his Google Calendar data usage, the Google OAuth service will redirect him back + * in this page. Here we are going to store the refresh token, because this is what will be used to generate access + * tokens in the future. + * + * IMPORTANT: Because it is necessary to authorize the application using the web server flow (see official + * documentation of OAuth), every Easy!Appointments installation should use its own calendar api key. So in every + * api console account, the "http://path-to-Easy!Appointments/google/oauth_callback" should be included in an allowed redirect URL. + */ + public function oauth_callback() + { + $code = $this->input->get('code'); + + if (empty($code)) + { + $this->output->set_output('Code authorization failed.'); + return; + } + + $this->load->library('Google_sync'); + + $token = $this->google_sync->authenticate($code); + + if (empty($token)) + { + $this->output->set_output('Token authorization failed.'); + return; + } + + // Store the token into the database for future reference. + $oauth_provider_id = $this->session->userdata('oauth_provider_id'); + + if ($oauth_provider_id) + { + $this->load->model('providers_model'); + $this->providers_model->set_setting('google_sync', TRUE, $oauth_provider_id); + $this->providers_model->set_setting('google_token', json_encode($token), $oauth_provider_id); + $this->providers_model->set_setting('google_calendar', 'primary', $oauth_provider_id); + } + else + { + $this->output->set_output('Sync provider id not specified.'); + } + } + + /** + * Complete synchronization of appointments between Google Calendar and Easy!Appointments. + * + * This method will completely sync the appointments of a provider with his Google Calendar account. The sync period + * needs to be relatively small, because a lot of API calls might be necessary and this will lead to consuming the + * Google limit for the Calendar API usage. + * + * @param int $provider_id Provider record to be synced. + */ + public static function sync($provider_id = NULL) + { + try + { + $framework = get_instance(); + + // The user must be logged in. + $framework->load->library('session'); + + if ($framework->session->userdata('user_id') == FALSE && is_cli() === FALSE) + { + return; + } + + if ($provider_id === NULL) + { + throw new Exception('Provider id not specified.'); + } + + $framework->load->model('appointments_model'); + $framework->load->model('providers_model'); + $framework->load->model('services_model'); + $framework->load->model('customers_model'); + $framework->load->model('settings_model'); + + $provider = $framework->providers_model->get_row($provider_id); + + // Check whether the selected provider has google sync enabled. + $google_sync = $framework->providers_model->get_setting('google_sync', $provider['id']); + + if ( ! $google_sync) + { + throw new Exception('The selected provider has not the google synchronization setting enabled.'); + } + + $google_token = json_decode($framework->providers_model->get_setting('google_token', $provider['id'])); + $framework->load->library('google_sync'); + $framework->google_sync->refresh_token($google_token->refresh_token); + + // Fetch provider's appointments that belong to the sync time period. + $sync_past_days = $framework->providers_model->get_setting('sync_past_days', $provider['id']); + $sync_future_days = $framework->providers_model->get_setting('sync_future_days', $provider['id']); + $start = strtotime('-' . $sync_past_days . ' days', strtotime(date('Y-m-d'))); + $end = strtotime('+' . $sync_future_days . ' days', strtotime(date('Y-m-d'))); + + $where_clause = [ + 'start_datetime >=' => date('Y-m-d H:i:s', $start), + 'end_datetime <=' => date('Y-m-d H:i:s', $end), + 'id_users_provider' => $provider['id'] + ]; + + $appointments = $framework->appointments_model->get_batch($where_clause); + + $company_settings = [ + 'company_name' => $framework->settings_model->get_setting('company_name'), + 'company_link' => $framework->settings_model->get_setting('company_link'), + 'company_email' => $framework->settings_model->get_setting('company_email') + ]; + + $provider_timezone = new DateTimeZone($provider['timezone']); + + // Sync each appointment with Google Calendar by following the project's sync protocol (see documentation). + foreach ($appointments as $appointment) + { + if ($appointment['is_unavailable'] == FALSE) + { + $service = $framework->services_model->get_row($appointment['id_services']); + $customer = $framework->customers_model->get_row($appointment['id_users_customer']); + } + else + { + $service = NULL; + $customer = NULL; + } + + // If current appointment not synced yet, add to Google Calendar. + if ($appointment['id_google_calendar'] == NULL) + { + $google_event = $framework->google_sync->add_appointment($appointment, $provider, + $service, $customer, $company_settings); + $appointment['id_google_calendar'] = $google_event->id; + $framework->appointments_model->add($appointment); // Save the Google Calendar ID. + } + else + { + // Appointment is synced with google calendar. + try + { + $google_event = $framework->google_sync->get_event($provider, $appointment['id_google_calendar']); + + if ($google_event->status == 'cancelled') + { + throw new Exception('Event is cancelled, remove the record from Easy!Appointments.'); + } + + // If Google Calendar event is different from Easy!Appointments appointment then update + // Easy!Appointments record. + $is_different = FALSE; + $appt_start = strtotime($appointment['start_datetime']); + $appt_end = strtotime($appointment['end_datetime']); + $event_start = new DateTime($google_event->getStart()->getDateTime()); + $event_start->setTimezone($provider_timezone); + $event_end = new DateTime($google_event->getEnd()->getDateTime()); + $event_end->setTimezone($provider_timezone); + + + if ($appt_start != $event_start->getTimestamp() || $appt_end != $event_end->getTimestamp() + || $appointment['notes'] !== $google_event->getDescription()) + { + $is_different = TRUE; + } + + if ($is_different) + { + $appointment['start_datetime'] = $event_start->format('Y-m-d H:i:s'); + $appointment['end_datetime'] = $event_end->format('Y-m-d H:i:s'); + $appointment['notes'] = $google_event->getDescription(); + $framework->appointments_model->add($appointment); + } + + } + catch (Exception $exception) + { + // Appointment not found on Google Calendar, delete from Easy!Appoinmtents. + $framework->appointments_model->delete($appointment['id']); + $appointment['id_google_calendar'] = NULL; + } + } + } + + // Add Google Calendar events that do not exist in Easy!Appointments. + $google_calendar = $provider['settings']['google_calendar']; + $google_events = $framework->google_sync->get_sync_events($google_calendar, $start, $end); + + foreach ($google_events->getItems() as $google_event) + { + if ($google_event->getStatus() === 'cancelled') + { + continue; + } + + if ($google_event->getStart() === NULL || $google_event->getEnd() === NULL) + { + continue; + } + + $results = $framework->appointments_model->get_batch(['id_google_calendar' => $google_event->getId()]); + + if ( ! empty($results)) + { + continue; + } + + $event_start = new DateTime($google_event->getStart()->getDateTime()); + $event_start->setTimezone($provider_timezone); + $event_end = new DateTime($google_event->getEnd()->getDateTime()); + $event_end->setTimezone($provider_timezone); + + // Record doesn't exist in the Easy!Appointments, so add the event now. + $appointment = [ + 'start_datetime' => $event_start->format('Y-m-d H:i:s'), + 'end_datetime' => $event_end->format('Y-m-d H:i:s'), + 'is_unavailable' => TRUE, + 'location' => $google_event->getLocation(), + 'notes' => $google_event->getSummary() . ' ' . $google_event->getDescription(), + 'id_users_provider' => $provider_id, + 'id_google_calendar' => $google_event->getId(), + 'id_users_customer' => NULL, + 'id_services' => NULL, + ]; + + $framework->appointments_model->add($appointment); + } + + $response = AJAX_SUCCESS; + } + catch (Exception $exception) + { + $framework->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $framework->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + +} diff --git a/application/controllers/Installation.php b/application/controllers/Installation.php new file mode 100644 index 00000000..bfb2c5a6 --- /dev/null +++ b/application/controllers/Installation.php @@ -0,0 +1,187 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.1.0 + * ---------------------------------------------------------------------------- */ + +/** + * Installation Controller + * + * This controller will handle the installation procedure of Easy!Appointments. + * + * @property CI_Session $session + * @property CI_Loader $load + * @property CI_Input $input + * @property CI_Output $output + * @property CI_Config $config + * @property CI_Lang $lang + * @property CI_Cache $cache + * @property CI_DB_query_builder $db + * @property CI_Security $security + * @property CI_Migration migration + * @property Google_Sync $google_sync + * @property Ics_file $ics_file + * @property Appointments_Model $appointments_model + * @property Providers_Model $providers_model + * @property Services_Model $services_model + * @property Customers_Model $customers_model + * @property Settings_Model $settings_model + * @property Timezones $timezones + * @property Roles_Model $roles_model + * @property Secretaries_Model $secretaries_model + * @property Admins_Model $admins_model + * @property User_Model $user_model + * + * @package Controllers + */ +class Installation extends CI_Controller { + /** + * Class Constructor + */ + public function __construct() + { + parent::__construct(); + + $this->load->helper('installation'); + $this->load->library('session'); + + if ($this->session->userdata('language')) + { + // Set user's selected language. + $this->config->set_item('language', $this->session->userdata('language')); + $this->lang->load('translations', $this->session->userdata('language')); + } + else + { + // Set the default language. + $this->lang->load('translations', $this->config->item('language')); + } + } + + /** + * Display the installation page. + */ + public function index() + { + if (is_app_installed()) + { + redirect('appointments/index'); + return; + } + + $this->load->view('general/installation', [ + 'base_url' => $this->config->item('base_url') + ]); + } + + /** + * [AJAX] Installs Easy!Appointments on the server. + */ + public function ajax_install() + { + try + { + if (is_app_installed()) + { + return; + } + + $this->load->model('admins_model'); + $this->load->model('settings_model'); + $this->load->model('services_model'); + $this->load->model('providers_model'); + $this->load->library('session'); + $this->load->library('migration'); + $this->load->helper('string'); + + $admin = $this->input->post('admin'); + $company = $this->input->post('company'); + + if ( ! $this->migration->current()) + { + throw new Exception($this->migration->error_string()); + } + + // Insert admin + $admin['timezone'] = 'UTC'; + $admin['settings']['username'] = $admin['username']; + $admin['settings']['password'] = $admin['password']; + $admin['settings']['notifications'] = true; + $admin['settings']['calendar_view'] = CALENDAR_VIEW_DEFAULT; + unset($admin['username'], $admin['password']); + $admin['id'] = $this->admins_model->add($admin); + + $this->session->set_userdata('user_id', $admin['id']); + $this->session->set_userdata('user_email', $admin['email']); + $this->session->set_userdata('role_slug', DB_SLUG_ADMIN); + $this->session->set_userdata('timezone', $admin['timezone']); + $this->session->set_userdata('username', $admin['settings']['username']); + + // Save company settings + $this->settings_model->set_setting('company_name', $company['company_name']); + $this->settings_model->set_setting('company_email', $company['company_email']); + $this->settings_model->set_setting('company_link', $company['company_link']); + + // Create sample records. + $services = [ + 'name' => 'Test Service', + 'duration' => 30, + 'price' => 50.0, + 'currency' => 'EUR', + 'description' => 'This is a test service automatically inserted by the installer.', + 'availabilities_type' => 'flexible', + 'attendants_number' => 1, + 'id_service_categories' => NULL + ]; + $services['id'] = $this->services_model->add($services); + + $salt = generate_salt(); + $password = random_string('alnum', 12); + + $sample_provider = [ + 'first_name' => 'John', + 'last_name' => 'Doe', + 'email' => 'john@example.org', + 'phone_number' => '0123456789', + 'services' => [ + $services['id'] + ], + 'settings' => [ + 'username' => 'johndoe', + 'password' => hash_password($salt, $password), + 'salt' => $salt, + 'working_plan' => '{"monday":{"start":"09:00","end":"18:00","breaks":[{"start":"14:30","end":"15:00"}]},"tuesday":{"start":"09:00","end":"18:00","breaks":[{"start":"14:30","end":"15:00"}]},"wednesday":{"start":"09:00","end":"18:00","breaks":[{"start":"14:30","end":"15:00"}]},"thursday":{"start":"09:00","end":"18:00","breaks":[{"start":"14:30","end":"15:00"}]},"friday":{"start":"09:00","end":"18:00","breaks":[{"start":"14:30","end":"15:00"}]},"saturday":null,"sunday":null}', + 'notifications' => FALSE, + 'google_sync' => FALSE, + 'sync_past_days' => 5, + 'sync_future_days' => 5, + 'calendar_view' => CALENDAR_VIEW_DEFAULT + ] + ]; + + $this->providers_model->add($sample_provider); + + $response = AJAX_SUCCESS; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } +} diff --git a/application/controllers/Privacy.php b/application/controllers/Privacy.php new file mode 100644 index 00000000..cf8647f3 --- /dev/null +++ b/application/controllers/Privacy.php @@ -0,0 +1,88 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.3.2 + * ---------------------------------------------------------------------------- */ + +/** + * Class Privacy + * + * @property CI_Session $session + * @property CI_Loader $load + * @property CI_Input $input + * @property CI_Output $output + * @property CI_Config $config + * @property CI_Lang $lang + * @property CI_Cache $cache + * @property CI_DB_query_builder $db + * @property CI_Security $security + * @property Google_Sync $google_sync + * @property Ics_file $ics_file + * @property Appointments_Model $appointments_model + * @property Providers_Model $providers_model + * @property Services_Model $services_model + * @property Customers_Model $customers_model + * @property Settings_Model $settings_model + * @property Timezones $timezones + * @property Roles_Model $roles_model + * @property Secretaries_Model $secretaries_model + * @property Admins_Model $admins_model + * @property User_Model $user_model + * + * @package Controllers + */ +class Privacy extends CI_Controller { + /** + * Remove all customer data (including appointments from the system). + */ + public function ajax_delete_personal_information() + { + try + { + $customer_token = $this->input->post('customer_token'); + + if (empty($customer_token)) + { + throw new InvalidArgumentException('Invalid customer token value provided.'); + } + + $this->load->driver('cache', ['adapter' => 'file']); + + $customer_id = $this->cache->get('customer-token-' . $customer_token); + + if (empty($customer_id)) + { + throw new InvalidArgumentException('Customer ID could not be found, please reload the page ' + . 'and try again.'); + } + + $this->load->model('customers_model'); + + $this->customers_model->delete($customer_id); + + $response = [ + 'success' => TRUE + ]; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } +} diff --git a/application/controllers/User.php b/application/controllers/User.php new file mode 100644 index 00000000..4223773e --- /dev/null +++ b/application/controllers/User.php @@ -0,0 +1,249 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +use EA\Engine\Notifications\Email as EmailClient; +use EA\Engine\Types\Email; +use EA\Engine\Types\NonEmptyText; + +/** + * User Controller + * + * @property CI_Session $session + * @property CI_Loader $load + * @property CI_Input $input + * @property CI_Output $output + * @property CI_Config $config + * @property CI_Lang $lang + * @property CI_Cache $cache + * @property CI_DB_query_builder $db + * @property CI_Security $security + * @property Google_Sync $google_sync + * @property Ics_file $ics_file + * @property Appointments_Model $appointments_model + * @property Providers_Model $providers_model + * @property Services_Model $services_model + * @property Customers_Model $customers_model + * @property Settings_Model $settings_model + * @property Timezones $timezones + * @property Roles_Model $roles_model + * @property Secretaries_Model $secretaries_model + * @property Admins_Model $admins_model + * @property User_Model $user_model + * + * @package Controllers + */ +class User extends CI_Controller { + /** + * Class Constructor + */ + public function __construct() + { + parent::__construct(); + + $this->load->library('session'); + + if ($this->session->userdata('language')) + { + // Set user's selected language. + $this->config->set_item('language', $this->session->userdata('language')); + $this->lang->load('translations', $this->session->userdata('language')); + } + else + { + // Set the default language. + $this->lang->load('translations', $this->config->item('language')); // default + } + } + + /** + * Default Method + * + * The default method will redirect the browser to the user/login URL. + */ + public function index() + { + header('Location: ' . site_url('user/login')); + } + + /** + * Display the login page. + * + * @throws Exception + */ + public function login() + { + $this->load->model('settings_model'); + + $view['base_url'] = $this->config->item('base_url'); + $view['dest_url'] = $this->session->userdata('dest_url'); + + if ( ! $view['dest_url']) + { + $view['dest_url'] = site_url('backend'); + } + + $view['company_name'] = $this->settings_model->get_setting('company_name'); + + $this->load->view('user/login', $view); + } + + /** + * Display the logout page. + */ + public function logout() + { + $this->load->model('settings_model'); + + $this->session->unset_userdata('user_id'); + $this->session->unset_userdata('user_email'); + $this->session->unset_userdata('role_slug'); + $this->session->unset_userdata('username'); + $this->session->unset_userdata('dest_url'); + + $view['base_url'] = $this->config->item('base_url'); + $view['company_name'] = $this->settings_model->get_setting('company_name'); + $this->load->view('user/logout', $view); + } + + /** + * Display the "forgot password" page. + * @throws Exception + */ + public function forgot_password() + { + $this->load->model('settings_model'); + $view['base_url'] = $this->config->item('base_url'); + $view['company_name'] = $this->settings_model->get_setting('company_name'); + $this->load->view('user/forgot_password', $view); + } + + /** + * Display the "not authorized" page. + * @throws Exception + */ + public function no_privileges() + { + $this->load->model('settings_model'); + $view['base_url'] = $this->config->item('base_url'); + $view['company_name'] = $this->settings_model->get_setting('company_name'); + $this->load->view('user/no_privileges', $view); + } + + /** + * [AJAX] Check whether the user has entered the correct login credentials. + * + * The session data of a logged in user are the following: + * - 'user_id' + * - 'user_email' + * - 'role_slug' + * - 'dest_url' + */ + public function ajax_check_login() + { + try + { + if ( ! $this->input->post('username') || ! $this->input->post('password')) + { + throw new Exception('Invalid credentials given!'); + } + + $this->load->model('user_model'); + + $user_data = $this->user_model->check_login($this->input->post('username'), $this->input->post('password')); + + if ($user_data) + { + $this->session->set_userdata($user_data); // Save data on user's session. + + $response = AJAX_SUCCESS; + } + else + { + $response = AJAX_FAILURE; + } + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } + + /** + * Regenerate a new password for the current user, only if the username and + * email address given correspond to an existing user in db. + * + * Required POST Parameters: + * + * - string $_POST['username'] Username to be validated. + * - string $_POST['email'] Email to be validated. + */ + public function ajax_forgot_password() + { + try + { + if ( ! $this->input->post('username') || ! $this->input->post('email')) + { + throw new Exception('You must enter a valid username and email address in ' + . 'order to get a new password!'); + } + + $this->load->model('user_model'); + $this->load->model('settings_model'); + + $new_password = $this->user_model->regenerate_password( + $this->input->post('username'), + $this->input->post('email') + ); + + if ($new_password != FALSE) + { + $this->config->load('email'); + + $email = new EmailClient($this, $this->config->config); + + $company_settings = [ + 'company_name' => $this->settings_model->get_setting('company_name'), + 'company_link' => $this->settings_model->get_setting('company_link'), + 'company_email' => $this->settings_model->get_setting('company_email') + ]; + + $email->sendPassword(new NonEmptyText($new_password), new Email($this->input->post('email')), + $company_settings); + } + + $response = $new_password != FALSE ? AJAX_SUCCESS : AJAX_FAILURE; + } + catch (Exception $exception) + { + $this->output->set_status_header(500); + + $response = [ + 'message' => $exception->getMessage(), + 'trace' => config('debug') ? $exception->getTrace() : [] + ]; + } + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($response)); + } +} diff --git a/src/application/controllers/api/index.html b/application/controllers/api/index.html similarity index 100% rename from src/application/controllers/api/index.html rename to application/controllers/api/index.html diff --git a/application/controllers/api/v1/API_V1_Controller.php b/application/controllers/api/v1/API_V1_Controller.php new file mode 100644 index 00000000..b27e529b --- /dev/null +++ b/application/controllers/api/v1/API_V1_Controller.php @@ -0,0 +1,173 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.2.0 + * ---------------------------------------------------------------------------- */ + +use EA\Engine\Api\V1\Authorization; +use EA\Engine\Types\NonEmptyText; + +/** + * API V1 Controller + * + * Parent controller class for the API v1 resources. Extend this class instead of the CI_Controller + * and call the parent constructor. + * + * @package Controllers + */ +class API_V1_Controller extends CI_Controller { + /** + * Class Constructor + * + * This constructor will handle the common operations of each API call. + * + * Important: Do not forget to call the this constructor from the child classes. + * + * Notice: At the time being only the basic authentication is supported. Make sure + * that you use the API through SSL/TLS for security. + */ + public function __construct() + { + try + { + parent::__construct(); + + $this->load->model('settings_model'); + + $api_token = $this->settings_model->get_setting('api_token'); + + $authorization = new Authorization($this); + + if ( ! empty($api_token) && $api_token === $this->_getBearerToken()) + { + return; + } + + if ( ! isset($_SERVER['PHP_AUTH_USER'])) + { + $this->_requestAuthentication(); + return; + } + + $username = new NonEmptyText($_SERVER['PHP_AUTH_USER']); + $password = new NonEmptyText($_SERVER['PHP_AUTH_PW']); + $authorization->basic($username, $password); + } + catch (Exception $exception) + { + exit($this->_handleException($exception)); + } + } + + /** + * Returns the bearer token value. + * + * @return string + */ + protected function _getBearerToken() + { + $headers = $this->_getAuthorizationHeader(); + + // HEADER: Get the access token from the header + + if ( ! empty($headers)) + { + if (preg_match('/Bearer\s(\S+)/', $headers, $matches)) + { + return $matches[1]; + } + } + return NULL; + } + + /** + * Returns the authorization header. + * + * @return string + */ + protected function _getAuthorizationHeader() + { + $headers = NULL; + + if (isset($_SERVER['Authorization'])) + { + $headers = trim($_SERVER['Authorization']); + } + else + { + if (isset($_SERVER['HTTP_AUTHORIZATION'])) + { + //Nginx or fast CGI + $headers = trim($_SERVER['HTTP_AUTHORIZATION']); + } + elseif (function_exists('apache_request_headers')) + { + $requestHeaders = apache_request_headers(); + + // Server-side fix for bug in old Android versions (a nice side-effect of this fix means we don't care + // about capitalization for Authorization). + $requestHeaders = array_combine(array_map('ucwords', array_keys($requestHeaders)), array_values($requestHeaders)); + + if (isset($requestHeaders['Authorization'])) + { + $headers = trim($requestHeaders['Authorization']); + } + } + } + + return $headers; + } + + /** + * Sets request authentication headers. + */ + protected function _requestAuthentication() + { + header('WWW-Authenticate: Basic realm="Easy!Appointments"'); + header('HTTP/1.0 401 Unauthorized'); + exit('You are not authorized to use the API.'); + } + + /** + * Outputs the required headers and messages for exception handling. + * + * Call this method from catch blocks of child controller callbacks. + * + * @param Exception $exception Thrown exception to be outputted. + */ + protected function _handleException(Exception $exception) + { + $error = [ + 'code' => $exception->getCode() ?: 500, + 'message' => $exception->getMessage(), + ]; + + $header = $exception instanceof \EA\Engine\Api\V1\Exception + ? $exception->getCode() . ' ' . $exception->getHeader() + : '500 Internal Server Error'; + + header('HTTP/1.0 ' . $header); + header('Content-Type: application/json'); + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($error, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)); + } + + /** + * Throw an API exception stating that the requested record was not found. + * + * @throws \EA\Engine\Api\V1\Exception + */ + protected function _throwRecordNotFound() + { + throw new \EA\Engine\Api\V1\Exception('The requested record was not found!', 404, 'Not Found'); + } +} diff --git a/application/controllers/api/v1/Admins.php b/application/controllers/api/v1/Admins.php new file mode 100644 index 00000000..3c4cea7c --- /dev/null +++ b/application/controllers/api/v1/Admins.php @@ -0,0 +1,188 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.2.0 + * ---------------------------------------------------------------------------- */ + +require_once __DIR__ . '/API_V1_Controller.php'; + +use EA\Engine\Api\V1\Request; +use EA\Engine\Api\V1\Response; +use EA\Engine\Types\NonEmptyText; + +/** + * Admins Controller + * + * @property CI_Session $session + * @property CI_Loader $load + * @property CI_Input $input + * @property CI_Output $output + * @property CI_Config $config + * @property CI_Lang $lang + * @property CI_Cache $cache + * @property CI_DB_query_builder $db + * @property CI_Security $security + * @property Google_Sync $google_sync + * @property Ics_file $ics_file + * @property Appointments_Model $appointments_model + * @property Providers_Model $providers_model + * @property Services_Model $services_model + * @property Customers_Model $customers_model + * @property Settings_Model $settings_model + * @property Timezones $timezones + * @property Roles_Model $roles_model + * @property Secretaries_Model $secretaries_model + * @property Admins_Model $admins_model + * @property User_Model $user_model + * + * @package Controllers + */ +class Admins extends API_V1_Controller { + /** + * Admins Resource Parser + * + * @var \EA\Engine\Api\V1\Parsers\Admins + */ + protected $parser; + + /** + * Class Constructor + */ + public function __construct() + { + parent::__construct(); + $this->load->model('admins_model'); + $this->parser = new \EA\Engine\Api\V1\Parsers\Admins; + } + + /** + * GET API Method + * + * @param int $id Optional (null), the record ID to be returned. + */ + public function get($id = NULL) + { + try + { + $condition = $id !== NULL ? 'id = ' . $id : NULL; + $admins = $this->admins_model->get_batch($condition); + + if ($id !== NULL && count($admins) === 0) + { + $this->_throwRecordNotFound(); + } + + $response = new Response($admins); + + $response->encode($this->parser) + ->search() + ->sort() + ->paginate() + ->minimize() + ->singleEntry($id) + ->output(); + + } + catch (Exception $exception) + { + $this->_handleException($exception); + } + } + + /** + * POST API Method + */ + public function post() + { + try + { + // Insert the admin to the database. + $request = new Request(); + $admin = $request->getBody(); + $this->parser->decode($admin); + + if (isset($admin['id'])) + { + unset($admin['id']); + } + + $id = $this->admins_model->add($admin); + + // Fetch the new object from the database and return it to the client. + $batch = $this->admins_model->get_batch('id = ' . $id); + $response = new Response($batch); + $status = new NonEmptyText('201 Created'); + $response->encode($this->parser)->singleEntry(TRUE)->output($status); + } + catch (Exception $exception) + { + $this->_handleException($exception); + } + } + + /** + * PUT API Method + * + * @param int $id The record ID to be updated. + */ + public function put($id) + { + try + { + // Update the admin record. + $batch = $this->admins_model->get_batch('id = ' . $id); + + if ($id !== NULL && count($batch) === 0) + { + $this->_throwRecordNotFound(); + } + + $request = new Request(); + $updatedAdmin = $request->getBody(); + $baseAdmin = $batch[0]; + $this->parser->decode($updatedAdmin, $baseAdmin); + $updatedAdmin['id'] = $id; + $id = $this->admins_model->add($updatedAdmin); + + // Fetch the updated object from the database and return it to the client. + $batch = $this->admins_model->get_batch('id = ' . $id); + $response = new Response($batch); + $response->encode($this->parser)->singleEntry($id)->output(); + } + catch (Exception $exception) + { + $this->_handleException($exception); + } + } + + /** + * DELETE API Method + * + * @param int $id The record ID to be deleted. + */ + public function delete($id) + { + try + { + $this->admins_model->delete($id); + + $response = new Response([ + 'code' => 200, + 'message' => 'Record was deleted successfully!' + ]); + + $response->output(); + } + catch (Exception $exception) + { + $this->_handleException($exception); + } + } +} diff --git a/application/controllers/api/v1/Appointments.php b/application/controllers/api/v1/Appointments.php new file mode 100644 index 00000000..d479dab8 --- /dev/null +++ b/application/controllers/api/v1/Appointments.php @@ -0,0 +1,211 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.2.0 + * ---------------------------------------------------------------------------- */ + +require_once __DIR__ . '/API_V1_Controller.php'; + +use EA\Engine\Api\V1\Request; +use EA\Engine\Api\V1\Response; +use EA\Engine\Types\NonEmptyText; + +/** + * Appointments Controller + * + * @property CI_Session $session + * @property CI_Loader $load + * @property CI_Input $input + * @property CI_Output $output + * @property CI_Config $config + * @property CI_Lang $lang + * @property CI_Cache $cache + * @property CI_DB_query_builder $db + * @property CI_Security $security + * @property Google_Sync $google_sync + * @property Ics_file $ics_file + * @property Appointments_Model $appointments_model + * @property Providers_Model $providers_model + * @property Services_Model $services_model + * @property Customers_Model $customers_model + * @property Settings_Model $settings_model + * @property Timezones $timezones + * @property Roles_Model $roles_model + * @property Secretaries_Model $secretaries_model + * @property Admins_Model $admins_model + * @property User_Model $user_model + * + * @package Controllers + */ +class Appointments extends API_V1_Controller { + /** + * Appointments Resource Parser + * + * @var \EA\Engine\Api\V1\Parsers\Appointments + */ + protected $parser; + + /** + * Class Constructor + */ + public function __construct() + { + parent::__construct(); + $this->load->model('appointments_model'); + $this->parser = new \EA\Engine\Api\V1\Parsers\Appointments; + } + + /** + * GET API Method + * + * @param int $id Optional (null), the record ID to be returned. + */ + public function get($id = NULL) + { + try + { + $conditions = [ + 'is_unavailable' => FALSE + ]; + + if ($id !== NULL) + { + $conditions['id'] = $id; + } + + $appointments = $this->appointments_model->get_batch($conditions, NULL, NULL, NULL, array_key_exists('aggregates', $_GET)); + + if ($id !== NULL && count($appointments) === 0) + { + $this->_throwRecordNotFound(); + } + + $response = new Response($appointments); + + $response->encode($this->parser) + ->search() + ->sort() + ->paginate() + ->minimize() + ->singleEntry($id) + ->output(); + + } + catch (Exception $exception) + { + exit($this->_handleException($exception)); + } + } + + /** + * POST API Method + */ + public function post() + { + $this->load->model('services_model'); + + try + { + // Insert the appointment to the database. + $request = new Request(); + $appointment = $request->getBody(); + $this->parser->decode($appointment); + + if (isset($appointment['id'])) + { + unset($appointment['id']); + } + + // Generate end_datetime based on service duration if this field is not defined + if ( ! isset($appointment['end_datetime'])) + { + $service = $this->services_model->get_row($appointment['id_services']); + + if (isset($service['duration'])) + { + $end_datetime = new DateTime($appointment['start_datetime']); + $end_datetime->add(new DateInterval('PT' . $service['duration'] . 'M')); + $appointment['end_datetime'] = $end_datetime->format('Y-m-d H:i:s'); + } + } + + $id = $this->appointments_model->add($appointment); + + // Fetch the new object from the database and return it to the client. + $batch = $this->appointments_model->get_batch('id = ' . $id); + $response = new Response($batch); + $status = new NonEmptyText('201 Created'); + $response->encode($this->parser)->singleEntry(TRUE)->output($status); + } + catch (Exception $exception) + { + exit($this->_handleException($exception)); + } + } + + /** + * PUT API Method + * + * @param int $id The record ID to be updated. + */ + public function put($id) + { + try + { + // Update the appointment record. + $batch = $this->appointments_model->get_batch('id = ' . $id); + + if ($id !== NULL && count($batch) === 0) + { + $this->_throwRecordNotFound(); + } + + $request = new Request(); + $updatedAppointment = $request->getBody(); + $baseAppointment = $batch[0]; + $this->parser->decode($updatedAppointment, $baseAppointment); + $updatedAppointment['id'] = $id; + $id = $this->appointments_model->add($updatedAppointment); + + // Fetch the updated object from the database and return it to the client. + $batch = $this->appointments_model->get_batch('id = ' . $id); + $response = new Response($batch); + $response->encode($this->parser)->singleEntry($id)->output(); + } + catch (Exception $exception) + { + exit($this->_handleException($exception)); + } + } + + /** + * DELETE API Method + * + * @param int $id The record ID to be deleted. + */ + public function delete($id) + { + try + { + $this->appointments_model->delete($id); + + $response = new Response([ + 'code' => 200, + 'message' => 'Record was deleted successfully!' + ]); + + $response->output(); + } + catch (Exception $exception) + { + exit($this->_handleException($exception)); + } + } +} diff --git a/application/controllers/api/v1/Availabilities.php b/application/controllers/api/v1/Availabilities.php new file mode 100644 index 00000000..a3501637 --- /dev/null +++ b/application/controllers/api/v1/Availabilities.php @@ -0,0 +1,568 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.2.0 + * ---------------------------------------------------------------------------- */ + +require_once __DIR__ . '/API_V1_Controller.php'; +require_once __DIR__ . '/../../Appointments.php'; + +use EA\Engine\Types\UnsignedInteger; + +/** + * Availabilities Controller + * + * @property CI_Session $session + * @property CI_Loader $load + * @property CI_Input $input + * @property CI_Output $output + * @property CI_Config $config + * @property CI_Lang $lang + * @property CI_Cache $cache + * @property CI_DB_query_builder $db + * @property CI_Security $security + * @property Google_Sync $google_sync + * @property Ics_file $ics_file + * @property Appointments_Model $appointments_model + * @property Providers_Model $providers_model + * @property Services_Model $services_model + * @property Customers_Model $customers_model + * @property Settings_Model $settings_model + * @property Timezones $timezones + * @property Roles_Model $roles_model + * @property Secretaries_Model $secretaries_model + * @property Admins_Model $admins_model + * @property User_Model $user_model + * + * @package Controllers + */ +class Availabilities extends API_V1_Controller { + /** + * Class Constructor + */ + public function __construct() + { + parent::__construct(); + $this->load->model('appointments_model'); + $this->load->model('providers_model'); + $this->load->model('services_model'); + $this->load->model('settings_model'); + } + + /** + * GET API Method + * + * Provide the "providerId", "serviceId" and "date" GET parameters to get the availabilities for a specific date. + * If no "date" was provided then the current date will be used. + */ + public function get() + { + try + { + $providerId = new UnsignedInteger($this->input->get('providerId')); + $serviceId = new UnsignedInteger($this->input->get('serviceId')); + + if ($this->input->get('date')) + { + $date = new DateTime($this->input->get('date')); + } + else + { + $date = new DateTime(); + } + + $provider = $this->providers_model->get_row($providerId->get()); + $service = $this->services_model->get_row($serviceId->get()); + + $emptyPeriods = $this->_getProviderAvailableTimePeriods($providerId->get(), + $date->format('Y-m-d'), []); + + $availableHours = $this->_calculateAvailableHours($emptyPeriods, + $date->format('Y-m-d'), $service['duration'], FALSE, $service['availabilities_type']); + + if ($service['attendants_number'] > 1) + { + $availableHours = $this->_getMultipleAttendantsHours($date->format('Y-m-d'), $service, $provider); + } + + // If the selected date is today, remove past hours. It is important include the timeout before + // booking that is set in the back-office the system. Normally we might want the customer to book + // an appointment that is at least half or one hour from now. The setting is stored in minutes. + if ($date->format('Y-m-d') === date('Y-m-d')) + { + $bookAdvanceTimeout = $this->settings_model->get_setting('book_advance_timeout'); + + foreach ($availableHours as $index => $value) + { + $availableHour = strtotime($value); + $currentHour = strtotime('+' . $bookAdvanceTimeout . ' minutes', strtotime('now')); + if ($availableHour <= $currentHour) + { + unset($availableHours[$index]); + } + } + } + + $availableHours = array_values($availableHours); + sort($availableHours, SORT_STRING); + $availableHours = array_values($availableHours); + + $this->output + ->set_content_type('application/json') + ->set_output(json_encode($availableHours)); + } + catch (Exception $exception) + { + exit($this->_handleException($exception)); + } + } + + /** + * Get an array containing the free time periods (start - end) of a selected date. + * + * This method is very important because there are many cases where the system needs to + * know when a provider is available for an appointment. This method will return an array + * that belongs to the selected date and contains values that have the start and the end + * time of an available time period. + * + * @param int $provider_id The provider's record id. + * @param string $selected_date The date to be checked (MySQL formatted string). + * @param array $exclude_appointments This array contains the ids of the appointments that + * will not be taken into consideration when the available time periods are calculated. + * + * @return array Returns an array with the available time periods of the provider. + */ + protected function _getProviderAvailableTimePeriods( + $provider_id, + $selected_date, + $exclude_appointments = [] + ) + { + $this->load->model('appointments_model'); + $this->load->model('providers_model'); + + // Get the provider's working plan and reserved appointments. + $working_plan = json_decode($this->providers_model->get_setting('working_plan', $provider_id), TRUE); + + // Get the provider's working plan exceptions. + $working_plan_exceptions = json_decode($this->providers_model->get_setting('working_plan_exceptions', $provider_id), TRUE); + + $where_clause = [ + 'id_users_provider' => $provider_id + ]; + + $reserved_appointments = $this->appointments_model->get_batch($where_clause); + + // Sometimes it might be necessary to not take into account some appointment records + // in order to display what the providers' available time periods would be without them. + foreach ($exclude_appointments as $excluded_id) + { + foreach ($reserved_appointments as $index => $reserved) + { + if ($reserved['id'] == $excluded_id) + { + unset($reserved_appointments[$index]); + } + } + } + + // Find the empty spaces on the plan. The first split between the plan is due to a break (if exist). After that + // every reserved appointment is considered to be a taken space in the plan. + $selected_date_working_plan = $working_plan[strtolower(date('l', strtotime($selected_date)))]; + + if (isset($working_plan_exceptions[$selected_date])) + { + $selected_date_working_plan = $working_plan_exceptions[$selected_date]; + } + + $available_periods_with_breaks = []; + + if (isset($selected_date_working_plan['breaks'])) + { + $start = new DateTime($selected_date_working_plan['start']); + $end = new DateTime($selected_date_working_plan['end']); + $available_periods_with_breaks[] = [ + 'start' => $selected_date_working_plan['start'], + 'end' => $selected_date_working_plan['end'] + ]; + + // Split the working plan to available time periods that do not contain the breaks in them. + foreach ($selected_date_working_plan['breaks'] as $index => $break) + { + $break_start = new DateTime($break['start']); + $break_end = new DateTime($break['end']); + + if ($break_start < $start) + { + $break_start = $start; + } + + if ($break_end > $end) + { + $break_end = $end; + } + + if ($break_start >= $break_end) + { + continue; + } + + foreach ($available_periods_with_breaks as $key => $open_period) + { + $s = new DateTime($open_period['start']); + $e = new DateTime($open_period['end']); + + if ($s < $break_end && $break_start < $e) + { // check for overlap + $changed = FALSE; + if ($s < $break_start) + { + $open_start = $s; + $open_end = $break_start; + $available_periods_with_breaks[] = [ + 'start' => $open_start->format('H:i'), + 'end' => $open_end->format('H:i') + ]; + $changed = TRUE; + } + + if ($break_end < $e) + { + $open_start = $break_end; + $open_end = $e; + $available_periods_with_breaks[] = [ + 'start' => $open_start->format('H:i'), + 'end' => $open_end->format('H:i') + ]; + $changed = TRUE; + } + + if ($changed) + { + unset($available_periods_with_breaks[$key]); + } + } + } + } + } + + // Break the empty periods with the reserved appointments. + $available_periods_with_appointments = $available_periods_with_breaks; + + foreach ($reserved_appointments as $appointment) + { + foreach ($available_periods_with_appointments as $index => &$period) + { + $a_start = strtotime($appointment['start_datetime']); + $a_end = strtotime($appointment['end_datetime']); + $p_start = strtotime($selected_date . ' ' . $period['start']); + $p_end = strtotime($selected_date . ' ' . $period['end']); + + if ($a_start <= $p_start && $a_end <= $p_end && $a_end <= $p_start) + { + // The appointment does not belong in this time period, so we + // will not change anything. + } + else + { + if ($a_start <= $p_start && $a_end <= $p_end && $a_end >= $p_start) + { + // The appointment starts before the period and finishes somewhere inside. + // We will need to break this period and leave the available part. + $period['start'] = date('H:i', $a_end); + } + else + { + if ($a_start >= $p_start && $a_end <= $p_end) + { + // The appointment is inside the time period, so we will split the period + // into two new others. + unset($available_periods_with_appointments[$index]); + $available_periods_with_appointments[] = [ + 'start' => date('H:i', $p_start), + 'end' => date('H:i', $a_start) + ]; + $available_periods_with_appointments[] = [ + 'start' => date('H:i', $a_end), + 'end' => date('H:i', $p_end) + ]; + } + else + { + if ($a_start >= $p_start && $a_end >= $p_start && $a_start <= $p_end) + { + // The appointment starts in the period and finishes out of it. We will + // need to remove the time that is taken from the appointment. + $period['end'] = date('H:i', $a_start); + } + else + { + if ($a_start >= $p_start && $a_end >= $p_end && $a_start >= $p_end) + { + // The appointment does not belong in the period so do not change anything. + } + else + { + if ($a_start <= $p_start && $a_end >= $p_end && $a_start <= $p_end) + { + // The appointment is bigger than the period, so this period needs to be removed. + unset($available_periods_with_appointments[$index]); + } + } + } + } + } + } + } + } + + return array_values($available_periods_with_appointments); + } + + /** + * Calculate the available appointment hours. + * + * Calculate the available appointment hours for the given date. The empty spaces + * are broken down to 15 min and if the service fit in each quarter then a new + * available hour is added to the "$available_hours" array. + * + * @param array $empty_periods Contains the empty periods as generated by the + * "_getProviderAvailableTimePeriods" method. + * @param string $selected_date The selected date to be search (format ) + * @param int $service_duration The service duration is required for the hour calculation. + * @param bool $manage_mode (optional) Whether we are currently on manage mode (editing an existing appointment). + * @param string $availabilities_type Optional ('flexible'), the service availabilities type. + * + * @return array Returns an array with the available hours for the appointment. + */ + protected function _calculateAvailableHours( + array $empty_periods, + $selected_date, + $service_duration, + $manage_mode = FALSE, + $availabilities_type = 'flexible' + ) + { + $this->load->model('settings_model'); + + $available_hours = []; + + foreach ($empty_periods as $period) + { + $start_hour = new DateTime($selected_date . ' ' . $period['start']); + $end_hour = new DateTime($selected_date . ' ' . $period['end']); + $interval = $availabilities_type === AVAILABILITIES_TYPE_FIXED ? (int)$service_duration : 15; + + $current_hour = $start_hour; + $diff = $current_hour->diff($end_hour); + + while (($diff->h * 60 + $diff->i) >= intval($service_duration)) + { + $available_hours[] = $current_hour->format('H:i'); + $current_hour->add(new DateInterval('PT' . $interval . 'M')); + $diff = $current_hour->diff($end_hour); + } + } + + return $available_hours; + } + + /** + * Get multiple attendants hours. + * + * This method will add the additional appointment hours whenever a service accepts multiple attendants. + * + * @param string $selected_date The selected appointment date. + * @param array $service Selected service data. + * @param array $provider Selected provider data. + * + * @return array Returns the available hours array. + */ + protected function _getMultipleAttendantsHours( + $selected_date, + $service, + $provider + ) + { + $this->load->model('appointments_model'); + $this->load->model('services_model'); + $this->load->model('providers_model'); + + $unavailabilities = $this->appointments_model->get_batch([ + 'is_unavailable' => TRUE, + 'DATE(start_datetime)' => $selected_date, + 'id_users_provider' => $provider['id'] + ]); + + $working_plan = json_decode($provider['settings']['working_plan'], TRUE); + $working_day = strtolower(date('l', strtotime($selected_date))); + $working_hours = $working_plan[$working_day]; + + $periods = [ + [ + 'start' => new DateTime($selected_date . ' ' . $working_hours['start']), + 'end' => new DateTime($selected_date . ' ' . $working_hours['end']) + ] + ]; + + $periods = $this->_removeBreaks($selected_date, $periods, $working_hours['breaks']); + $periods = $this->_removeUnavailabilities($periods, $unavailabilities); + + $hours = []; + + $interval_value = $service['availabilities_type'] == AVAILABILITIES_TYPE_FIXED ? $service['duration'] : '15'; + $interval = new DateInterval('PT' . (int)$interval_value . 'M'); + $duration = new DateInterval('PT' . (int)$service['duration'] . 'M'); + + foreach ($periods as $period) + { + $slot_start = clone $period['start']; + $slot_end = clone $slot_start; + $slot_end->add($duration); + + while ($slot_end <= $period['end']) + { + // Check reserved attendants for this time slot and see if current attendants fit. + $appointment_attendants_number = $this->appointments_model->get_attendants_number_for_period($slot_start, + $slot_end, $service['id']); + + if ($appointment_attendants_number < $service['attendants_number']) + { + $hours[] = $slot_start->format('H:i'); + } + + $slot_start->add($interval); + $slot_end->add($interval); + } + } + + return $hours; + } + + /** + * Remove breaks from available time periods. + * + * @param string $selected_date Selected data (Y-m-d format). + * @param array $periods Time periods of the current date. + * @param array $breaks Breaks array for the current date. + * + * @return array Returns the available time periods without the breaks. + */ + public function _removeBreaks($selected_date, $periods, $breaks) + { + if ( ! $breaks) + { + return $periods; + } + + foreach ($breaks as $break) + { + $break_start = new DateTime($selected_date . ' ' . $break['start']); + $break_end = new DateTime($selected_date . ' ' . $break['end']); + + foreach ($periods as &$period) + { + $period_start = $period['start']; + $period_end = $period['end']; + + if ($break_start <= $period_start && $break_end >= $period_start && $break_end <= $period_end) + { + // left + $period['start'] = $break_end; + continue; + } + + if ($break_start >= $period_start && $break_start <= $period_end && $break_end >= $period_start && $break_end <= $period_end) + { + // middle + $period['end'] = $break_start; + $periods[] = [ + 'start' => $break_end, + 'end' => $period_end + ]; + continue; + } + + if ($break_start >= $period_start && $break_start <= $period_end && $break_end >= $period_end) + { + // right + $period['end'] = $break_start; + continue; + } + + if ($break_start <= $period_start && $break_end >= $period_end) + { + // break contains period + $period['start'] = $break_end; + continue; + } + } + } + + return $periods; + } + + /** + * Remove the unavailabilities from the available time periods of the selected date. + * + * @param array $periods Available time periods. + * @param array $unavailabilities Unavailabilities of the current date. + * + * @return array Returns the available time periods without the unavailabilities. + */ + public function _removeUnavailabilities($periods, $unavailabilities) + { + foreach ($unavailabilities as $unavailability) + { + $unavailability_start = new DateTime($unavailability['start_datetime']); + $unavailability_end = new DateTime($unavailability['end_datetime']); + + foreach ($periods as &$period) + { + $period_start = $period['start']; + $period_end = $period['end']; + + if ($unavailability_start <= $period_start && $unavailability_end >= $period_start && $unavailability_end <= $period_end) + { + // left + $period['start'] = $unavailability_end; + continue; + } + + if ($unavailability_start >= $period_start && $unavailability_start <= $period_end && $unavailability_end >= $period_start && $unavailability_end <= $period_end) + { + // middle + $period['end'] = $unavailability_start; + $periods[] = [ + 'start' => $unavailability_end, + 'end' => $period_end + ]; + continue; + } + + if ($unavailability_start >= $period_start && $unavailability_start <= $period_end && $unavailability_end >= $period_end) + { + // right + $period['end'] = $unavailability_start; + continue; + } + + if ($unavailability_start <= $period_start && $unavailability_end >= $period_end) + { + // Unavaibility contains period + $period['start'] = $unavailability_end; + continue; + } + } + } + + return $periods; + } +} diff --git a/application/controllers/api/v1/Categories.php b/application/controllers/api/v1/Categories.php new file mode 100644 index 00000000..eb5a6649 --- /dev/null +++ b/application/controllers/api/v1/Categories.php @@ -0,0 +1,188 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.2.0 + * ---------------------------------------------------------------------------- */ + +require_once __DIR__ . '/API_V1_Controller.php'; + +use EA\Engine\Api\V1\Request; +use EA\Engine\Api\V1\Response; +use EA\Engine\Types\NonEmptyText; + +/** + * Categories Controller + * + * @property CI_Session $session + * @property CI_Loader $load + * @property CI_Input $input + * @property CI_Output $output + * @property CI_Config $config + * @property CI_Lang $lang + * @property CI_Cache $cache + * @property CI_DB_query_builder $db + * @property CI_Security $security + * @property Google_Sync $google_sync + * @property Ics_file $ics_file + * @property Appointments_Model $appointments_model + * @property Providers_Model $providers_model + * @property Services_Model $services_model + * @property Customers_Model $customers_model + * @property Settings_Model $settings_model + * @property Timezones $timezones + * @property Roles_Model $roles_model + * @property Secretaries_Model $secretaries_model + * @property Admins_Model $admins_model + * @property User_Model $user_model + * + * @package Controllers + */ +class Categories extends API_V1_Controller { + /** + * Categories Resource Parser + * + * @var \EA\Engine\Api\V1\Parsers\Categories + */ + protected $parser; + + /** + * Class Constructor + */ + public function __construct() + { + parent::__construct(); + $this->load->model('services_model'); + $this->parser = new \EA\Engine\Api\V1\Parsers\Categories; + } + + /** + * GET API Method + * + * @param int $id Optional (null), the record ID to be returned. + */ + public function get($id = NULL) + { + try + { + $condition = $id !== NULL ? 'id = ' . $id : ''; + $categories = $this->services_model->get_all_categories($condition); + + if ($id !== NULL && count($categories) === 0) + { + $this->_throwRecordNotFound(); + } + + $response = new Response($categories); + + $response->encode($this->parser) + ->search() + ->sort() + ->paginate() + ->minimize() + ->singleEntry($id) + ->output(); + + } + catch (Exception $exception) + { + $this->_handleException($exception); + } + } + + /** + * POST API Method + */ + public function post() + { + try + { + // Insert the category to the database. + $request = new Request(); + $category = $request->getBody(); + $this->parser->decode($category); + + if (isset($category['id'])) + { + unset($category['id']); + } + + $id = $this->services_model->add_category($category); + + // Fetch the new object from the database and return it to the client. + $batch = $this->services_model->get_all_categories('id = ' . $id); + $response = new Response($batch); + $status = new NonEmptyText('201 Created'); + $response->encode($this->parser)->singleEntry(TRUE)->output($status); + } + catch (Exception $exception) + { + $this->_handleException($exception); + } + } + + /** + * PUT API Method + * + * @param int $id The record ID to be updated. + */ + public function put($id) + { + try + { + // Update the category record. + $batch = $this->services_model->get_all_categories('id = ' . $id); + + if ($id !== NULL && count($batch) === 0) + { + $this->_throwRecordNotFound(); + } + + $request = new Request(); + $updatedCategory = $request->getBody(); + $baseCategory = $batch[0]; + $this->parser->decode($updatedCategory, $baseCategory); + $updatedCategory['id'] = $id; + $id = $this->services_model->add_category($updatedCategory); + + // Fetch the updated object from the database and return it to the client. + $batch = $this->services_model->get_all_categories('id = ' . $id); + $response = new Response($batch); + $response->encode($this->parser)->singleEntry($id)->output(); + } + catch (Exception $exception) + { + $this->_handleException($exception); + } + } + + /** + * DELETE API Method + * + * @param int $id The record ID to be deleted. + */ + public function delete($id) + { + try + { + $result = $this->services_model->delete_category($id); + + $response = new Response([ + 'code' => 200, + 'message' => 'Record was deleted successfully!' + ]); + + $response->output(); + } + catch (Exception $exception) + { + $this->_handleException($exception); + } + } +} diff --git a/application/controllers/api/v1/Customers.php b/application/controllers/api/v1/Customers.php new file mode 100644 index 00000000..e2d9a332 --- /dev/null +++ b/application/controllers/api/v1/Customers.php @@ -0,0 +1,188 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.2.0 + * ---------------------------------------------------------------------------- */ + +require_once __DIR__ . '/API_V1_Controller.php'; + +use EA\Engine\Api\V1\Request; +use EA\Engine\Api\V1\Response; +use EA\Engine\Types\NonEmptyText; + +/** + * Customers Controller + * + * @property CI_Session $session + * @property CI_Loader $load + * @property CI_Input $input + * @property CI_Output $output + * @property CI_Config $config + * @property CI_Lang $lang + * @property CI_Cache $cache + * @property CI_DB_query_builder $db + * @property CI_Security $security + * @property Google_Sync $google_sync + * @property Ics_file $ics_file + * @property Appointments_Model $appointments_model + * @property Providers_Model $providers_model + * @property Services_Model $services_model + * @property Customers_Model $customers_model + * @property Settings_Model $settings_model + * @property Timezones $timezones + * @property Roles_Model $roles_model + * @property Secretaries_Model $secretaries_model + * @property Admins_Model $admins_model + * @property User_Model $user_model + * + * @package Controllers + */ +class Customers extends API_V1_Controller { + /** + * Customers Resource Parser + * + * @var \EA\Engine\Api\V1\Parsers\Customers + */ + protected $parser; + + /** + * Class Constructor + */ + public function __construct() + { + parent::__construct(); + $this->load->model('customers_model'); + $this->parser = new \EA\Engine\Api\V1\Parsers\Customers; + } + + /** + * GET API Method + * + * @param int $id Optional (null), the record ID to be returned. + */ + public function get($id = NULL) + { + try + { + $condition = $id !== NULL ? 'id = ' . $id : NULL; + $customers = $this->customers_model->get_batch($condition); + + if ($id !== NULL && count($customers) === 0) + { + $this->_throwRecordNotFound(); + } + + $response = new Response($customers); + + $response->encode($this->parser) + ->search() + ->sort() + ->paginate() + ->minimize() + ->singleEntry($id) + ->output(); + + } + catch (Exception $exception) + { + $this->_handleException($exception); + } + } + + /** + * POST API Method + */ + public function post() + { + try + { + // Insert the customer to the database. + $request = new Request(); + $customer = $request->getBody(); + $this->parser->decode($customer); + + if (isset($customer['id'])) + { + unset($customer['id']); + } + + $id = $this->customers_model->add($customer); + + // Fetch the new object from the database and return it to the client. + $batch = $this->customers_model->get_batch('id = ' . $id); + $response = new Response($batch); + $status = new NonEmptyText('201 Created'); + $response->encode($this->parser)->singleEntry(TRUE)->output($status); + } + catch (Exception $exception) + { + $this->_handleException($exception); + } + } + + /** + * PUT API Method + * + * @param int $id The record ID to be updated. + */ + public function put($id) + { + try + { + // Update the customer record. + $batch = $this->customers_model->get_batch('id = ' . $id); + + if ($id !== NULL && count($batch) === 0) + { + $this->_throwRecordNotFound(); + } + + $request = new Request(); + $updatedCustomer = $request->getBody(); + $baseCustomer = $batch[0]; + $this->parser->decode($updatedCustomer, $baseCustomer); + $updatedCustomer['id'] = $id; + $id = $this->customers_model->add($updatedCustomer); + + // Fetch the updated object from the database and return it to the client. + $batch = $this->customers_model->get_batch('id = ' . $id); + $response = new Response($batch); + $response->encode($this->parser)->singleEntry($id)->output(); + } + catch (Exception $exception) + { + $this->_handleException($exception); + } + } + + /** + * DELETE API Method + * + * @param int $id The record ID to be deleted. + */ + public function delete($id) + { + try + { + $result = $this->customers_model->delete($id); + + $response = new Response([ + 'code' => 200, + 'message' => 'Record was deleted successfully!' + ]); + + $response->output(); + } + catch (Exception $exception) + { + $this->_handleException($exception); + } + } +} diff --git a/application/controllers/api/v1/Providers.php b/application/controllers/api/v1/Providers.php new file mode 100644 index 00000000..2918e053 --- /dev/null +++ b/application/controllers/api/v1/Providers.php @@ -0,0 +1,188 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.2.0 + * ---------------------------------------------------------------------------- */ + +require_once __DIR__ . '/API_V1_Controller.php'; + +use EA\Engine\Api\V1\Request; +use EA\Engine\Api\V1\Response; +use EA\Engine\Types\NonEmptyText; + +/** + * Providers Controller + * + * @property CI_Session $session + * @property CI_Loader $load + * @property CI_Input $input + * @property CI_Output $output + * @property CI_Config $config + * @property CI_Lang $lang + * @property CI_Cache $cache + * @property CI_DB_query_builder $db + * @property CI_Security $security + * @property Google_Sync $google_sync + * @property Ics_file $ics_file + * @property Appointments_Model $appointments_model + * @property Providers_Model $providers_model + * @property Services_Model $services_model + * @property Customers_Model $customers_model + * @property Settings_Model $settings_model + * @property Timezones $timezones + * @property Roles_Model $roles_model + * @property Secretaries_Model $secretaries_model + * @property Admins_Model $admins_model + * @property User_Model $user_model + * + * @package Controllers + */ +class Providers extends API_V1_Controller { + /** + * Providers Resource Parser + * + * @var \EA\Engine\Api\V1\Parsers\Providers + */ + protected $parser; + + /** + * Class Constructor + */ + public function __construct() + { + parent::__construct(); + $this->load->model('providers_model'); + $this->parser = new \EA\Engine\Api\V1\Parsers\Providers; + } + + /** + * GET API Method + * + * @param int $id Optional (null), the record ID to be returned. + */ + public function get($id = NULL) + { + try + { + $condition = $id !== NULL ? 'id = ' . $id : NULL; + $providers = $this->providers_model->get_batch($condition); + + if ($id !== NULL && count($providers) === 0) + { + $this->_throwRecordNotFound(); + } + + $response = new Response($providers); + + $response->encode($this->parser) + ->search() + ->sort() + ->paginate() + ->minimize() + ->singleEntry($id) + ->output(); + + } + catch (Exception $exception) + { + $this->_handleException($exception); + } + } + + /** + * POST API Method + */ + public function post() + { + try + { + // Insert the provider to the database. + $request = new Request(); + $provider = $request->getBody(); + $this->parser->decode($provider); + + if (isset($provider['id'])) + { + unset($provider['id']); + } + + $id = $this->providers_model->add($provider); + + // Fetch the new object from the database and return it to the client. + $batch = $this->providers_model->get_batch('id = ' . $id); + $response = new Response($batch); + $status = new NonEmptyText('201 Created'); + $response->encode($this->parser)->singleEntry(TRUE)->output($status); + } + catch (Exception $exception) + { + $this->_handleException($exception); + } + } + + /** + * PUT API Method + * + * @param int $id The record ID to be updated. + */ + public function put($id) + { + try + { + // Update the provider record. + $batch = $this->providers_model->get_batch('id = ' . $id); + + if ($id !== NULL && count($batch) === 0) + { + $this->_throwRecordNotFound(); + } + + $request = new Request(); + $updatedProvider = $request->getBody(); + $baseProvider = $batch[0]; + $this->parser->decode($updatedProvider, $baseProvider); + $updatedProvider['id'] = $id; + $id = $this->providers_model->add($updatedProvider); + + // Fetch the updated object from the database and return it to the client. + $batch = $this->providers_model->get_batch('id = ' . $id); + $response = new Response($batch); + $response->encode($this->parser)->singleEntry($id)->output(); + } + catch (Exception $exception) + { + $this->_handleException($exception); + } + } + + /** + * DELETE API Method + * + * @param int $id The record ID to be deleted. + */ + public function delete($id) + { + try + { + $result = $this->providers_model->delete($id); + + $response = new Response([ + 'code' => 200, + 'message' => 'Record was deleted successfully!' + ]); + + $response->output(); + } + catch (Exception $exception) + { + $this->_handleException($exception); + } + } +} diff --git a/application/controllers/api/v1/Secretaries.php b/application/controllers/api/v1/Secretaries.php new file mode 100644 index 00000000..605fd711 --- /dev/null +++ b/application/controllers/api/v1/Secretaries.php @@ -0,0 +1,188 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.2.0 + * ---------------------------------------------------------------------------- */ + +require_once __DIR__ . '/API_V1_Controller.php'; + +use EA\Engine\Api\V1\Request; +use EA\Engine\Api\V1\Response; +use EA\Engine\Types\NonEmptyText; + +/** + * Secretaries Controller + * + * @property CI_Session $session + * @property CI_Loader $load + * @property CI_Input $input + * @property CI_Output $output + * @property CI_Config $config + * @property CI_Lang $lang + * @property CI_Cache $cache + * @property CI_DB_query_builder $db + * @property CI_Security $security + * @property Google_Sync $google_sync + * @property Ics_file $ics_file + * @property Appointments_Model $appointments_model + * @property Providers_Model $providers_model + * @property Services_Model $services_model + * @property Customers_Model $customers_model + * @property Settings_Model $settings_model + * @property Timezones $timezones + * @property Roles_Model $roles_model + * @property Secretaries_Model $secretaries_model + * @property Admins_Model $admins_model + * @property User_Model $user_model + * + * @package Controllers + */ +class Secretaries extends API_V1_Controller { + /** + * Secretaries Resource Parser + * + * @var \EA\Engine\Api\V1\Parsers\Secretaries + */ + protected $parser; + + /** + * Class Constructor + */ + public function __construct() + { + parent::__construct(); + $this->load->model('secretaries_model'); + $this->parser = new \EA\Engine\Api\V1\Parsers\Secretaries; + } + + /** + * GET API Method + * + * @param int $id Optional (null), the record ID to be returned. + */ + public function get($id = NULL) + { + try + { + $condition = $id !== NULL ? 'id = ' . $id : NULL; + $secretaries = $this->secretaries_model->get_batch($condition); + + if ($id !== NULL && count($secretaries) === 0) + { + $this->_throwRecordNotFound(); + } + + $response = new Response($secretaries); + + $response->encode($this->parser) + ->search() + ->sort() + ->paginate() + ->minimize() + ->singleEntry($id) + ->output(); + + } + catch (Exception $exception) + { + $this->_handleException($exception); + } + } + + /** + * POST API Method + */ + public function post() + { + try + { + // Insert the secretary to the database. + $request = new Request(); + $secretary = $request->getBody(); + $this->parser->decode($secretary); + + if (isset($secretary['id'])) + { + unset($secretary['id']); + } + + $id = $this->secretaries_model->add($secretary); + + // Fetch the new object from the database and return it to the client. + $batch = $this->secretaries_model->get_batch('id = ' . $id); + $response = new Response($batch); + $status = new NonEmptyText('201 Created'); + $response->encode($this->parser)->singleEntry(TRUE)->output($status); + } + catch (Exception $exception) + { + $this->_handleException($exception); + } + } + + /** + * PUT API Method + * + * @param int $id The record ID to be updated. + */ + public function put($id) + { + try + { + // Update the secretary record. + $batch = $this->secretaries_model->get_batch('id = ' . $id); + + if ($id !== NULL && count($batch) === 0) + { + $this->_throwRecordNotFound(); + } + + $request = new Request(); + $updatedSecretary = $request->getBody(); + $baseSecretary = $batch[0]; + $this->parser->decode($updatedSecretary, $baseSecretary); + $updatedSecretary['id'] = $id; + $id = $this->secretaries_model->add($updatedSecretary); + + // Fetch the updated object from the database and return it to the client. + $batch = $this->secretaries_model->get_batch('id = ' . $id); + $response = new Response($batch); + $response->encode($this->parser)->singleEntry($id)->output(); + } + catch (Exception $exception) + { + $this->_handleException($exception); + } + } + + /** + * DELETE API Method + * + * @param int $id The record ID to be deleted. + */ + public function delete($id) + { + try + { + $result = $this->secretaries_model->delete($id); + + $response = new Response([ + 'code' => 200, + 'message' => 'Record was deleted successfully!' + ]); + + $response->output(); + } + catch (Exception $exception) + { + $this->_handleException($exception); + } + } +} diff --git a/application/controllers/api/v1/Services.php b/application/controllers/api/v1/Services.php new file mode 100644 index 00000000..6aa9ccf1 --- /dev/null +++ b/application/controllers/api/v1/Services.php @@ -0,0 +1,188 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.2.0 + * ---------------------------------------------------------------------------- */ + +require_once __DIR__ . '/API_V1_Controller.php'; + +use EA\Engine\Api\V1\Request; +use EA\Engine\Api\V1\Response; +use EA\Engine\Types\NonEmptyText; + +/** + * Services Controller + * + * @property CI_Session $session + * @property CI_Loader $load + * @property CI_Input $input + * @property CI_Output $output + * @property CI_Config $config + * @property CI_Lang $lang + * @property CI_Cache $cache + * @property CI_DB_query_builder $db + * @property CI_Security $security + * @property Google_Sync $google_sync + * @property Ics_file $ics_file + * @property Appointments_Model $appointments_model + * @property Providers_Model $providers_model + * @property Services_Model $services_model + * @property Customers_Model $customers_model + * @property Settings_Model $settings_model + * @property Timezones $timezones + * @property Roles_Model $roles_model + * @property Secretaries_Model $secretaries_model + * @property Admins_Model $admins_model + * @property User_Model $user_model + * + * @package Controllers + */ +class Services extends API_V1_Controller { + /** + * Services Resource Parser + * + * @var \EA\Engine\Api\V1\Parsers\Services + */ + protected $parser; + + /** + * Class Constructor + */ + public function __construct() + { + parent::__construct(); + $this->load->model('services_model'); + $this->parser = new \EA\Engine\Api\V1\Parsers\Services; + } + + /** + * GET API Method + * + * @param int $id Optional (null), the record ID to be returned. + */ + public function get($id = NULL) + { + try + { + $condition = $id !== NULL ? 'id = ' . $id : NULL; + $services = $this->services_model->get_batch($condition); + + if ($id !== NULL && count($services) === 0) + { + $this->_throwRecordNotFound(); + } + + $response = new Response($services); + + $response->encode($this->parser) + ->search() + ->sort() + ->paginate() + ->minimize() + ->singleEntry($id) + ->output(); + + } + catch (Exception $exception) + { + $this->_handleException($exception); + } + } + + /** + * POST API Method + */ + public function post() + { + try + { + // Insert the service to the database. + $request = new Request(); + $service = $request->getBody(); + $this->parser->decode($service); + + if (isset($service['id'])) + { + unset($service['id']); + } + + $id = $this->services_model->add($service); + + // Fetch the new object from the database and return it to the client. + $batch = $this->services_model->get_batch('id = ' . $id); + $response = new Response($batch); + $status = new NonEmptyText('201 Created'); + $response->encode($this->parser)->singleEntry(TRUE)->output($status); + } + catch (Exception $exception) + { + $this->_handleException($exception); + } + } + + /** + * PUT API Method + * + * @param int $id The record ID to be updated. + */ + public function put($id) + { + try + { + // Update the service record. + $batch = $this->services_model->get_batch('id = ' . $id); + + if ($id !== NULL && count($batch) === 0) + { + $this->_throwRecordNotFound(); + } + + $request = new Request(); + $updatedService = $request->getBody(); + $baseService = $batch[0]; + $this->parser->decode($updatedService, $baseService); + $updatedService['id'] = $id; + $id = $this->services_model->add($updatedService); + + // Fetch the updated object from the database and return it to the client. + $batch = $this->services_model->get_batch('id = ' . $id); + $response = new Response($batch); + $response->encode($this->parser)->singleEntry($id)->output(); + } + catch (Exception $exception) + { + $this->_handleException($exception); + } + } + + /** + * DELETE API Method + * + * @param int $id The record ID to be deleted. + */ + public function delete($id) + { + try + { + $result = $this->services_model->delete($id); + + $response = new Response([ + 'code' => 200, + 'message' => 'Record was deleted successfully!' + ]); + + $response->output(); + } + catch (Exception $exception) + { + $this->_handleException($exception); + } + } +} diff --git a/application/controllers/api/v1/Settings.php b/application/controllers/api/v1/Settings.php new file mode 100644 index 00000000..19a82f28 --- /dev/null +++ b/application/controllers/api/v1/Settings.php @@ -0,0 +1,168 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.2.0 + * ---------------------------------------------------------------------------- */ + +require_once __DIR__ . '/API_V1_Controller.php'; + +use EA\Engine\Api\V1\Request; +use EA\Engine\Api\V1\Response; + +/** + * Settings Controller + * + * @property CI_Session $session + * @property CI_Loader $load + * @property CI_Input $input + * @property CI_Output $output + * @property CI_Config $config + * @property CI_Lang $lang + * @property CI_Cache $cache + * @property CI_DB_query_builder $db + * @property CI_Security $security + * @property Google_Sync $google_sync + * @property Ics_file $ics_file + * @property Appointments_Model $appointments_model + * @property Providers_Model $providers_model + * @property Services_Model $services_model + * @property Customers_Model $customers_model + * @property Settings_Model $settings_model + * @property Timezones $timezones + * @property Roles_Model $roles_model + * @property Secretaries_Model $secretaries_model + * @property Admins_Model $admins_model + * @property User_Model $user_model + * + * @package Controllers + */ +class Settings extends API_V1_Controller { + /** + * Settings Resource Parser + * + * @var \EA\Engine\Api\V1\Parsers\Settings + */ + protected $parser; + + /** + * Class Constructor + */ + public function __construct() + { + parent::__construct(); + $this->load->model('settings_model'); + $this->parser = new \EA\Engine\Api\V1\Parsers\Settings; + } + + /** + * GET API Method + * + * @param string $name Optional (null), the setting name to be returned. + */ + public function get($name = NULL) + { + try + { + $settings = $this->settings_model->get_settings(); + + if ($name !== NULL) + { + $setting = NULL; + + foreach ($settings as $entry) + { + if ($entry['name'] === $name) + { + $setting = $entry; + break; + } + } + + if (empty($setting)) + { + $this->_throwRecordNotFound(); + } + + unset($setting['id']); + + $settings = [ + $setting + ]; + } + + $response = new Response($settings); + + $response->encode($this->parser) + ->search() + ->sort() + ->paginate() + ->minimize() + ->singleEntry($name) + ->output(); + + } + catch (Exception $exception) + { + exit($this->_handleException($exception)); + } + } + + /** + * PUT API Method + * + * @param string $name The setting name to be inserted/updated. + */ + public function put($name) + { + try + { + $request = new Request(); + $value = $request->getBody()['value']; + $this->settings_model->set_setting($name, $value); + + // Fetch the updated object from the database and return it to the client. + $response = new Response([ + [ + 'name' => $name, + 'value' => $value + ] + ]); + $response->encode($this->parser)->singleEntry($name)->output(); + } + catch (Exception $exception) + { + exit($this->_handleException($exception)); + } + } + + /** + * DELETE API Method + * + * @param string $name The setting name to be deleted. + */ + public function delete($name) + { + try + { + $result = $this->settings_model->remove_setting($name); + + $response = new Response([ + 'code' => 200, + 'message' => 'Record was deleted successfully!' + ]); + + $response->output(); + } + catch (Exception $exception) + { + exit($this->_handleException($exception)); + } + } +} diff --git a/application/controllers/api/v1/Unavailabilities.php b/application/controllers/api/v1/Unavailabilities.php new file mode 100644 index 00000000..bc2cc2c9 --- /dev/null +++ b/application/controllers/api/v1/Unavailabilities.php @@ -0,0 +1,188 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.2.0 + * ---------------------------------------------------------------------------- */ + +require_once __DIR__ . '/API_V1_Controller.php'; + +use EA\Engine\Api\V1\Request; +use EA\Engine\Api\V1\Response; +use EA\Engine\Types\NonEmptyText; + +/** + * Unavailabilities Controller + * + * @property CI_Session $session + * @property CI_Loader $load + * @property CI_Input $input + * @property CI_Output $output + * @property CI_Config $config + * @property CI_Lang $lang + * @property CI_Cache $cache + * @property CI_DB_query_builder $db + * @property CI_Security $security + * @property Google_Sync $google_sync + * @property Ics_file $ics_file + * @property Appointments_Model $appointments_model + * @property Providers_Model $providers_model + * @property Services_Model $services_model + * @property Customers_Model $customers_model + * @property Settings_Model $settings_model + * @property Timezones $timezones + * @property Roles_Model $roles_model + * @property Secretaries_Model $secretaries_model + * @property Admins_Model $admins_model + * @property User_Model $user_model + * + * @package Controllers + */ +class Unavailabilities extends API_V1_Controller { + /** + * Unavailabilities Resource Parser + * + * @var \EA\Engine\Api\V1\Parsers\Unavailabilities + */ + protected $parser; + + /** + * Class Constructor + */ + public function __construct() + { + parent::__construct(); + $this->load->model('appointments_model'); + $this->parser = new \EA\Engine\Api\V1\Parsers\Unavailabilities; + } + + /** + * GET API Method + * + * @param int $id Optional (null), the record ID to be returned. + */ + public function get($id = NULL) + { + try + { + $condition = $id !== NULL ? 'id = ' . $id : 'is_unavailable = 1'; + $unavailabilities = $this->appointments_model->get_batch($condition); + + if ($id !== NULL && count($unavailabilities) === 0) + { + $this->_throwRecordNotFound(); + } + + $response = new Response($unavailabilities); + + $response->encode($this->parser) + ->search() + ->sort() + ->paginate() + ->minimize() + ->singleEntry($id) + ->output(); + + } + catch (Exception $exception) + { + exit($this->_handleException($exception)); + } + } + + /** + * POST API Method + */ + public function post() + { + try + { + // Insert the appointment to the database. + $request = new Request(); + $unavailability = $request->getBody(); + $this->parser->decode($unavailability); + + if (isset($unavailability['id'])) + { + unset($unavailability['id']); + } + + $id = $this->appointments_model->add_unavailable($unavailability); + + // Fetch the new object from the database and return it to the client. + $batch = $this->appointments_model->get_batch('id = ' . $id); + $response = new Response($batch); + $status = new NonEmptyText('201 Created'); + $response->encode($this->parser)->singleEntry(TRUE)->output($status); + } + catch (Exception $exception) + { + exit($this->_handleException($exception)); + } + } + + /** + * PUT API Method + * + * @param int $id The record ID to be updated. + */ + public function put($id) + { + try + { + // Update the appointment record. + $batch = $this->appointments_model->get_batch('id = ' . $id); + + if ($id !== NULL && count($batch) === 0) + { + $this->_throwRecordNotFound(); + } + + $request = new Request(); + $updatedUnavailability = $request->getBody(); + $baseUnavailability = $batch[0]; + $this->parser->decode($updatedUnavailability, $baseUnavailability); + $updatedUnavailability['id'] = $id; + $id = $this->appointments_model->add_unavailable($updatedUnavailability); + + // Fetch the updated object from the database and return it to the client. + $batch = $this->appointments_model->get_batch('id = ' . $id); + $response = new Response($batch); + $response->encode($this->parser)->singleEntry($id)->output(); + } + catch (Exception $exception) + { + exit($this->_handleException($exception)); + } + } + + /** + * DELETE API Method + * + * @param int $id The record ID to be deleted. + */ + public function delete($id) + { + try + { + $result = $this->appointments_model->delete_unavailable($id); + + $response = new Response([ + 'code' => 200, + 'message' => 'Record was deleted successfully!' + ]); + + $response->output(); + } + catch (Exception $exception) + { + exit($this->_handleException($exception)); + } + } +} diff --git a/src/application/controllers/api/v1/index.html b/application/controllers/api/v1/index.html similarity index 100% rename from src/application/controllers/api/v1/index.html rename to application/controllers/api/v1/index.html diff --git a/src/application/controllers/index.html b/application/controllers/index.html similarity index 100% rename from src/application/controllers/index.html rename to application/controllers/index.html diff --git a/application/helpers/asset_helper.php b/application/helpers/asset_helper.php new file mode 100644 index 00000000..b16af5dd --- /dev/null +++ b/application/helpers/asset_helper.php @@ -0,0 +1,44 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.3.0 + * ---------------------------------------------------------------------------- */ + +/** + * Assets URL helper function. + * + * This function will create an asset file URL that includes a cache busting parameter in order + * to invalidate the browser cache in case of an update. + * + * @param string $uri Relative URI (just like the one used in the base_url helper). + * @param string|null $protocol Valid URI protocol. + * + * @return string Returns the final asset URL. + */ +function asset_url($uri = '', $protocol = NULL) +{ + $framework =& get_instance(); + + $debug = $framework->config->item('debug'); + + $cache_busting_token = ! $debug ? '?' . $framework->config->item('cache_busting_token') : ''; + + if (strpos(basename($uri), '.js') !== FALSE && strpos(basename($uri), '.min.js') === FALSE && ! $debug) + { + $uri = str_replace('.js', '.min.js', $uri); + } + + if (strpos(basename($uri), '.css') !== FALSE && strpos(basename($uri), '.min.css') === FALSE && ! $debug) + { + $uri = str_replace('.css', '.min.css', $uri); + } + + return base_url($uri . $cache_busting_token, $protocol); +} diff --git a/application/helpers/config_helper.php b/application/helpers/config_helper.php new file mode 100644 index 00000000..3776e0de --- /dev/null +++ b/application/helpers/config_helper.php @@ -0,0 +1,26 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.3.0 + * ---------------------------------------------------------------------------- */ + +/** + * Quickly fetch the value of a framework configuration. + * + * @param string $key Configuration key. + * + * @return mixed Returns the configuration value. + */ +function config($key) +{ + $framework = &get_instance(); + + return $framework->config->item($key); +} diff --git a/application/helpers/custom_exceptions_helper.php b/application/helpers/custom_exceptions_helper.php new file mode 100644 index 00000000..64865197 --- /dev/null +++ b/application/helpers/custom_exceptions_helper.php @@ -0,0 +1,44 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +/** + * Print an exception to an HTML text. + * + * This method is used to display exceptions in a way that is useful and easy + * for the user to see. It uses the Bootstrap CSS accordion markup to display + * the message and when the user clicks on it the exception trace will be revealed. + * We display only one exceptions at a time because the user needs to be able + * to display the details of each exception seperately. (In contrast with js). + * + * @param Exception $exception The exception to be displayed. + * @return string Returns the html markup of the exception. + */ +function exceptionToHtml($exception) +{ + return + '
+
+ +
+
+
' . $exception->getTraceAsString() . '
+
+
+
+
'; +} diff --git a/application/helpers/data_validation_helper.php b/application/helpers/data_validation_helper.php new file mode 100644 index 00000000..1d73e3e6 --- /dev/null +++ b/application/helpers/data_validation_helper.php @@ -0,0 +1,28 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +/** + * Check if a string date is valid for insertion or update + * to the database. + * + * @param string $datetime The given date. + * @return bool Returns the validation result. + * + * @link http://stackoverflow.com/a/8105844/1718162 [SOURCE] + */ +function validate_mysql_datetime($datetime) +{ + $dt = DateTime::createFromFormat('Y-m-d H:i:s', $datetime); + + return $dt ? TRUE : FALSE; +} diff --git a/application/helpers/general_helper.php b/application/helpers/general_helper.php new file mode 100644 index 00000000..407d6b9a --- /dev/null +++ b/application/helpers/general_helper.php @@ -0,0 +1,85 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +/** + * Get date in RFC3339 + * + * For example used in XML/Atom + * + * @link http://stackoverflow.com/questions/5671433/php-time-to-google-calendar-dates-time-format + * + * @param integer $timestamp + * + * @return string date in RFC3339 + * + * @author Boris Korobkov + */ +function date3339($timestamp = 0) +{ + if ( ! $timestamp) + { + $timestamp = time(); + } + $date = date('Y-m-d\TH:i:s', $timestamp); + + $matches = []; + if (preg_match('/^([\-+])(\d{2})(\d{2})$/', date('O', $timestamp), $matches)) + { + $date .= $matches[1] . $matches[2] . ':' . $matches[3]; + } + else + { + $date .= 'Z'; + } + return $date; +} + +/** + * Generate a hash of password string. + * + * For user security, all system passwords are stored in hash string into the database. Use this method to produce the + * hashed password. + * + * @param string $salt Salt value for current user. This value is stored on the database and is used when generating + * the password hash. + * @param string $password Given string password. + * + * @return string Returns the hash string of the given password. + */ +function hash_password($salt, $password) +{ + $half = (int)(strlen($salt) / 2); + $hash = hash('sha256', substr($salt, 0, $half) . $password . substr($salt, $half)); + + for ($i = 0; $i < 100000; $i++) + { + $hash = hash('sha256', $hash); + } + + return $hash; +} + +/** + * Generate a new password salt. + * + * This method will not check if the salt is unique in database. This must be done + * from the calling procedure. + * + * @return string Returns a salt string. + */ +function generate_salt() +{ + $max_length = 100; + $salt = hash('sha256', (uniqid(rand(), TRUE))); + return substr($salt, 0, $max_length); +} diff --git a/application/helpers/google_analytics_helper.php b/application/helpers/google_analytics_helper.php new file mode 100644 index 00000000..db5a2338 --- /dev/null +++ b/application/helpers/google_analytics_helper.php @@ -0,0 +1,42 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.1.0 + * ---------------------------------------------------------------------------- */ + +/** + * Print Google Analytics script. + * + * This helper function should be used in view files in order to output the Google Analytics script. It will check + * whether the code is set in the database and print it, otherwise nothing will be outputted. This eliminates the need + * for extra checking before outputting. + */ +function google_analytics_script() +{ + $framework =& get_instance(); + + $framework->load->model('settings_model'); + + $google_analytics_code = $framework->settings_model->get_setting('google_analytics_code'); + + if ($google_analytics_code !== '') + { + echo ' + + '; + } +} diff --git a/src/application/helpers/index.html b/application/helpers/index.html similarity index 100% rename from src/application/helpers/index.html rename to application/helpers/index.html diff --git a/application/helpers/installation_helper.php b/application/helpers/installation_helper.php new file mode 100644 index 00000000..6c78978b --- /dev/null +++ b/application/helpers/installation_helper.php @@ -0,0 +1,29 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.1.0 + * ---------------------------------------------------------------------------- */ + +/** + * Check if Easy!Appointments is installed. + * + * This function will check some factors to determine if Easy!Appointments is installed or not. It is possible that the + * installation is properly configure without being recognized by this method. + * + * Notice: You can add more checks into this file in order to further check the installation state of the application. + * + * @return bool Returns whether E!A is installed or not. + */ +function is_app_installed() +{ + $framework =& get_instance(); + + return $framework->db->table_exists('users'); +} diff --git a/application/helpers/render_helper.php b/application/helpers/render_helper.php new file mode 100644 index 00000000..84e6a595 --- /dev/null +++ b/application/helpers/render_helper.php @@ -0,0 +1,33 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.4.0 + * ---------------------------------------------------------------------------- */ + +/** + * Render the HTML output of a timezone dropdown element. + * + * @param string $attributes HTML element attributes of the dropdown. + * @return false|string + */ +function render_timezone_dropdown($attributes = '') +{ + $framework = get_instance(); + + $framework->load->library('timezones'); + + $timezones = $framework->timezones->to_grouped_array(); + + ob_start(); + + require __DIR__ . '/../views/partial/timezone_dropdown.php'; + + return ob_get_clean(); +} diff --git a/src/application/index.html b/application/index.html similarity index 100% rename from src/application/index.html rename to application/index.html diff --git a/src/application/language/arabic/db_lang.php b/application/language/arabic/db_lang.php similarity index 100% rename from src/application/language/arabic/db_lang.php rename to application/language/arabic/db_lang.php diff --git a/src/application/language/arabic/email_lang.php b/application/language/arabic/email_lang.php similarity index 100% rename from src/application/language/arabic/email_lang.php rename to application/language/arabic/email_lang.php diff --git a/src/application/language/arabic/index.html b/application/language/arabic/index.html similarity index 100% rename from src/application/language/arabic/index.html rename to application/language/arabic/index.html diff --git a/src/application/language/arabic/migration_lang.php b/application/language/arabic/migration_lang.php similarity index 100% rename from src/application/language/arabic/migration_lang.php rename to application/language/arabic/migration_lang.php diff --git a/application/language/arabic/translations_lang.php b/application/language/arabic/translations_lang.php new file mode 100755 index 00000000..b450c97e --- /dev/null +++ b/application/language/arabic/translations_lang.php @@ -0,0 +1,323 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +/** + * Google Synchronization Class + * + * This class implements all the core synchronization between the Google Calendar + * and the Easy!Appointments system. Do not place any model handling inside this + * library. + * + * @package Libraries + */ +class Google_Sync { + /** + * CodeIgniter Instance + * + * @var CI_Controller + */ + protected $framework; + + /** + * Google API Client + * + * @var Google_Client + */ + protected $client; + + /** + * Google Calendar Service + * + * @var Google_Service_Calendar + */ + protected $service; + + /** + * Class Constructor + * + * This method initializes the Google client class and the Calendar service + * class so that they can be used by the other methods. + */ + public function __construct() + { + $this->framework =& get_instance(); + + $this->framework->load->library('session'); + + // Initialize google client and calendar service. + $this->client = new Google_Client(); + + $this->client->setApplicationName($this->framework->config->item('google_application_name')); + $this->client->setClientId($this->framework->config->item('google_client_id')); + $this->client->setClientSecret($this->framework->config->item('google_client_secret')); + $this->client->setDeveloperKey($this->framework->config->item('google_api_key')); + $this->client->setRedirectUri(site_url('google/oauth_callback')); + $this->client->setAccessType('offline'); + $this->client->addScope([ + Google_Service_Calendar::CALENDAR, + Google_Service_Calendar::CALENDAR_READONLY + ]); + + $this->service = new Google_Service_Calendar($this->client); + } + + /** + * Get Google OAuth authorization url. + * + * This url must be used to redirect the user to the Google user consent page, + * where the user grants access to his data for the Easy!Appointments app. + */ + public function get_auth_url() + { + // "max_auth_age" is needed because the user needs to always log in + // and not use an existing session. + return $this->client->createAuthUrl() . '&max_auth_age=0'; + } + + /** + * Authenticate the Google API usage. + * + * When the user grants consent for his data usage, google is going to redirect + * the browser back to the given redirect url. There a authentication code is + * provided. Using this code, we can authenticate the API usage and store the + * token information to the database. + * + * @param $code + * + * @return array + * + * @throws Exception + */ + public function authenticate($code) + { + $response = $this->client->fetchAccessTokenWithAuthCode($code); + + if (isset($response['error'])) + { + throw new Exception('Google Authentication Error (' . $response['error'] . '): ' . $response['error_description']); + } + + return $response; + } + + /** + * Refresh the Google Client access token. + * + * This method must be executed every time we need to make actions on a + * provider's Google Calendar account. A new token is necessary and the + * only way to get it is to use the stored refresh token that was provided + * when the provider granted consent to Easy!Appointments for use his + * Google Calendar account. + * + * @param string $refresh_token The provider's refresh token. This value is + * stored in the database and used every time we need to make actions to his + * Google Caledar account. + */ + public function refresh_token($refresh_token) + { + $this->client->refreshToken($refresh_token); + } + + /** + * Add an appointment record to its providers Google Calendar account. + * + * This method checks whether the appointment's provider has enabled the Google Sync utility of Easy!Appointments + * and the stored access token is still valid. If yes, the selected appointment record is going to be added to the + * Google Calendar account. + * + * @param array $appointment Contains the appointment record data. + * @param array $provider Contains the provider record data. + * @param array $service Contains the service record data. + * @param array $customer Contains the customer recod data. + * @param array $settings Contains some company settings that are used by this method. + * + * @return Google_Service_Calendar_Event Returns the Google_Event class object. + */ + public function add_appointment($appointment, $provider, $service, $customer, $settings) + { + $this->framework->load->helper('general'); + + $event = new Google_Service_Calendar_Event(); + $event->setSummary(($service != NULL) ? $service['name'] : 'Unavailable'); + $event->setDescription($appointment['notes']); + $event->setLocation(isset($appointment['location']) ? $appointment['location'] : $settings['company_name']); + + $start = new Google_Service_Calendar_EventDateTime(); + $start->setDateTime(date3339(strtotime($appointment['start_datetime']))); + $event->setStart($start); + + $end = new Google_Service_Calendar_EventDateTime(); + $end->setDateTime(date3339(strtotime($appointment['end_datetime']))); + $event->setEnd($end); + + $event->attendees = []; + + $event_provider = new Google_Service_Calendar_EventAttendee(); + $event_provider->setDisplayName($provider['first_name'] . ' ' + . $provider['last_name']); + $event_provider->setEmail($provider['email']); + $event->attendees[] = $event_provider; + + if ($customer != NULL) + { + $event_customer = new Google_Service_Calendar_EventAttendee(); + $event_customer->setDisplayName($customer['first_name'] . ' ' + . $customer['last_name']); + $event_customer->setEmail($customer['email']); + $event->attendees[] = $event_customer; + } + + // Add the new event to the google calendar. + $created_event = $this->service->events->insert($provider['settings']['google_calendar'], $event); + + return $created_event; + } + + /** + * Update an existing appointment that is already synced with Google Calendar. + * + * This method updates the google calendar event item that is connected with the + * provided appointment record of Easy!Appointments. + * + * @param array $appointment Contains the appointment record data. + * @param array $provider Contains the provider record data. + * @param array $service Contains the service record data. + * @param array $customer Contains the customer recod data. + * @parma array $settings Contains some company settings that are used by this method. + * + * @return Google_Service_Calendar_Event Returns the Google_Service_Calendar_Event class object. + */ + public function update_appointment($appointment, $provider, $service, $customer, $settings) + { + $this->framework->load->helper('general'); + + $event = $this->service->events->get($provider['settings']['google_calendar'], + $appointment['id_google_calendar']); + + $event->setSummary($service['name']); + $event->setDescription($appointment['notes']); + $event->setLocation(isset($appointment['location']) ? $appointment['location'] : $settings['company_name']); + + $start = new Google_Service_Calendar_EventDateTime(); + $start->setDateTime(date3339(strtotime($appointment['start_datetime']))); + $event->setStart($start); + + $end = new Google_Service_Calendar_EventDateTime(); + $end->setDateTime(date3339(strtotime($appointment['end_datetime']))); + $event->setEnd($end); + + $event->attendees = []; + + $event_provider = new Google_Service_Calendar_EventAttendee(); + $event_provider->setDisplayName($provider['first_name'] . ' ' + . $provider['last_name']); + $event_provider->setEmail($provider['email']); + $event->attendees[] = $event_provider; + + if ($customer != NULL) + { + $event_customer = new Google_Service_Calendar_EventAttendee(); + $event_customer->setDisplayName($customer['first_name'] . ' ' + . $customer['last_name']); + $event_customer->setEmail($customer['email']); + $event->attendees[] = $event_customer; + } + + $updated_event = $this->service->events->update($provider['settings']['google_calendar'], + $event->getId(), $event); + + return $updated_event; + } + + /** + * Delete an existing appointment from Google Calendar. + * + * @param array $provider Contains the provider record data. + * @param string $google_event_id The Google Calendar event id to + * be deleted. + */ + public function delete_appointment($provider, $google_event_id) + { + try + { + $this->service->events->delete($provider['settings']['google_calendar'], $google_event_id); + } + catch (Exception $ex) + { + // Event was not found on Google Calendar. + } + } + + /** + * Add unavailable period event to Google Calendar. + * + * @param array $provider Contains the provider record data. + * @param array $unavailable Contains unavailable period's data. + * + * @return Google_Service_Calendar_Event Returns the google event's object. + */ + public function add_unavailable($provider, $unavailable) + { + $this->framework->load->helper('general'); + + $event = new Google_Service_Calendar_Event(); + $event->setSummary('Unavailable'); + $event->setDescription($unavailable['notes']); + + $start = new Google_Service_Calendar_EventDateTime(); + $start->setDateTime(date3339(strtotime($unavailable['start_datetime']))); + $event->setStart($start); + + $end = new Google_Service_Calendar_EventDateTime(); + $end->setDateTime(date3339(strtotime($unavailable['end_datetime']))); + $event->setEnd($end); + + // Add the new event to the google calendar. + $created_event = $this->service->events->insert($provider['settings']['google_calendar'], $event); + + return $created_event; + + } + + /** + * Update Google Calendar unavailable period event. + * + * @param array $provider Contains the provider record data. + * @param array $unavailable Contains the unavailable period data. + * + * @return Google_Service_Calendar_Event Returns the Google_Service_Calendar_Event object. + */ + public function update_unavailable($provider, $unavailable) + { + $this->framework->load->helper('general'); + + $event = $this->service->events->get($provider['settings']['google_calendar'], + $unavailable['id_google_calendar']); + $event->setDescription($unavailable['notes']); + + $start = new Google_Service_Calendar_EventDateTime(); + $start->setDateTime(date3339(strtotime($unavailable['start_datetime']))); + $event->setStart($start); + + $end = new Google_Service_Calendar_EventDateTime(); + $end->setDateTime(date3339(strtotime($unavailable['end_datetime']))); + $event->setEnd($end); + + $updated_event = $this->service->events->update($provider['settings']['google_calendar'], + $event->getId(), $event); + + return $updated_event; + } + + /** + * Delete unavailable period event from Google Calendar. + * + * @param array $provider Contains the provider record data. + * @param string $google_event_id Google Calendar event id to be deleted. + */ + public function delete_unavailable($provider, $google_event_id) + { + try + { + $this->service->events->delete($provider['settings']['google_calendar'], $google_event_id); + } + catch (Exception $ex) + { + // Event was not found on Google Calendar. + } + } + + /** + * Get an event object from gcal + * + * @param array $provider Contains the provider record data. + * @param string $google_event_id Id of the google calendar event. + * + * @return Google_Service_Calendar_Event Returns the google event object. + */ + public function get_event($provider, $google_event_id) + { + return $this->service->events->get($provider['settings']['google_calendar'], $google_event_id); + } + + /** + * Get all the events between the sync period. + * + * @param string $google_calendar The name of the google calendar to be used. + * @param string $start The start date of sync period. + * @param string $end The end date of sync period. + * + * @return object Returns an array with Google_Service_Calendar_Event objects that belong on the given + * sync period (start, end). + */ + public function get_sync_events($google_calendar, $start, $end) + { + $this->framework->load->helper('general'); + + $params = [ + 'timeMin' => date3339($start), + 'timeMax' => date3339($end), + 'singleEvents' => TRUE, + ]; + + return $this->service->events->listEvents($google_calendar, $params); + } + + /** + * Return available google calendars for specific user. + * + * The given user's token must already exist in db in order to get access to his + * Google Calendar account. + * + * @param string $google_token The user's token will be used to grant access to google calendar. + * + * @return array Returns an array with the available calendars. + */ + public function get_google_calendars() + { + $calendarList = $this->service->calendarList->listCalendarList(); + $calendars = []; + foreach ($calendarList->items as $google_calendar) + { + if ($google_calendar->getAccessRole() === 'reader') + { + continue; + } + + $calendars[] = [ + 'id' => $google_calendar->id, + 'summary' => $google_calendar->summary + ]; + } + return $calendars; + } +} diff --git a/application/libraries/Ics_file.php b/application/libraries/Ics_file.php new file mode 100644 index 00000000..28056de8 --- /dev/null +++ b/application/libraries/Ics_file.php @@ -0,0 +1,168 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.3.0 + * ---------------------------------------------------------------------------- */ + +use Jsvrcek\ICS\CalendarExport; +use Jsvrcek\ICS\CalendarStream; +use Jsvrcek\ICS\Exception\CalendarEventException; +use Jsvrcek\ICS\Model\Calendar; +use Jsvrcek\ICS\Model\CalendarAlarm; +use Jsvrcek\ICS\Model\CalendarEvent; +use Jsvrcek\ICS\Model\Description\Location; +use Jsvrcek\ICS\Model\Relationship\Attendee; +use Jsvrcek\ICS\Model\Relationship\Organizer; +use Jsvrcek\ICS\Utility\Formatter; + +/** + * Class Ics_file + * + * An ICS file is a calendar file saved in a universal calendar format used by several email and calendar programs, + * including Microsoft Outlook, Google Calendar, and Apple Calendar. + * + * Depends on the Jsvrcek\ICS composer package. + */ +class Ics_file { + /** + * Get the ICS file contents for the provided arguments. + * + * @param array $appointment Appointment. + * @param array $service Service. + * @param array $provider Provider. + * @param array $customer Customer. + * + * @return string Returns the contents of the ICS file. + * + * @throws CalendarEventException + * @throws Exception + */ + public function get_stream($appointment, $service, $provider, $customer) + { + $appointment_timezone = new DateTimeZone($provider['timezone']); + + $appointment_start = new DateTime($appointment['start_datetime'], $appointment_timezone); + $appointment_end = new DateTime($appointment['end_datetime'], $appointment_timezone); + + // Setup the event. + $event = new CalendarEvent(); + + $event + ->setStart($appointment_start) + ->setEnd($appointment_end) + ->setStatus('CONFIRMED') + ->setSummary($service['name']) + ->setUid($appointment['id']); + + if (!empty($service['location'])) + { + $location = new Location(); + $location->setName((string)$service['location']); + $event->addLocation($location); + } + + $description = [ + '', + lang('provider'), + '', + lang('name') . ': ' . $provider['first_name'] . ' ' . $provider['last_name'], + lang('email') .': ' . $provider['email'], + lang('phone_number') . ': ' . $provider['phone_number'], + lang('address') . ': ' . $provider['address'], + lang('city') . ': ' . $provider['city'], + lang('zip_code') . ': ' . $provider['zip_code'], + '', + lang('customer'), + '', + lang('name') . ': ' . $customer['first_name'] . ' ' . $customer['last_name'], + lang('email') .': ' . $customer['email'], + lang('phone_number') . ': ' . $customer['phone_number'], + lang('address') . ': ' . $customer['address'], + lang('city') . ': ' . $customer['city'], + lang('zip_code') . ': ' . $customer['zip_code'], + '', + lang('notes'), + '', + $appointment['notes'], + ]; + + $event->setDescription(implode("\\n", $description)); + + $attendee = new Attendee(new Formatter()); + + if (isset($customer['email']) && ! empty($customer['email'])) + { + $attendee->setValue($customer['email']); + } + + // Add the event attendees. + $attendee->setName($customer['first_name'] . ' ' . $customer['last_name']); + $attendee->setCalendarUserType('INDIVIDUAL') + ->setRole('REQ-PARTICIPANT') + ->setParticipationStatus('NEEDS-ACTION') + ->setRsvp('TRUE'); + $event->addAttendee($attendee); + + $alarm = new CalendarAlarm(); + $alarm_datetime = clone $appointment_start; + $alarm->setTrigger($alarm_datetime->modify('-15 minutes')); + $alarm->setSummary('Alarm notification'); + $alarm->setDescription('This is an event reminder'); + $alarm->setAction('EMAIL'); + $alarm->addAttendee($attendee); + $event->addAlarm($alarm); + + $alarm = new CalendarAlarm(); + $alarm_datetime = clone $appointment_start; + $alarm->setTrigger($alarm_datetime->modify('-60 minutes')); + $alarm->setSummary('Alarm notification'); + $alarm->setDescription('This is an event reminder'); + $alarm->setAction('EMAIL'); + $alarm->addAttendee($attendee); + $event->addAlarm($alarm); + + $attendee = new Attendee(new Formatter()); + + if (isset($provider['email']) && ! empty($provider['email'])) + { + $attendee->setValue($provider['email']); + } + + $attendee->setName($provider['first_name'] . ' ' . $provider['last_name']); + $attendee->setCalendarUserType('INDIVIDUAL') + ->setRole('REQ-PARTICIPANT') + ->setParticipationStatus('ACCEPTED') + ->setRsvp('FALSE'); + $event->addAttendee($attendee); + + // Set the organizer. + $organizer = new Organizer(new Formatter()); + + $organizer + ->setValue($provider['email']) + ->setName($provider['first_name'] . ' ' . $provider['last_name']); + + $event->setOrganizer($organizer); + + // Setup calendar. + $calendar = new Calendar(); + + $calendar + ->setProdId('-//EasyAppointments//Open Source Web Scheduler//EN') + ->setTimezone(new DateTimeZone(date_default_timezone_get())) + ->addEvent($event); + + // Setup exporter. + $calendarExport = new CalendarExport(new CalendarStream, new Formatter()); + $calendarExport->addCalendar($calendar); + + return $calendarExport->getStream(); + } +} diff --git a/application/libraries/Timezones.php b/application/libraries/Timezones.php new file mode 100644 index 00000000..0a28c6ac --- /dev/null +++ b/application/libraries/Timezones.php @@ -0,0 +1,592 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.4.0 + * ---------------------------------------------------------------------------- */ + +/** + * Timezones + * + * @property CI_Loader $load + * + * @package Models + */ +class Timezones { + /** + * @var CI_Controller + */ + protected $framework; + + /** + * @var string + */ + protected $default = 'UTC'; + + /** + * @var array + */ + protected $timezones = [ + 'UTC' => [ + 'UTC' => 'UTC' + ], + 'America' => [ + 'America/Adak' => 'Adak (-10:00)', + 'America/Atka' => 'Atka (-10:00)', + 'America/Anchorage' => 'Anchorage (-9:00)', + 'America/Juneau' => 'Juneau (-9:00)', + 'America/Nome' => 'Nome (-9:00)', + 'America/Yakutat' => 'Yakutat (-9:00)', + 'America/Dawson' => 'Dawson (-8:00)', + 'America/Ensenada' => 'Ensenada (-8:00)', + 'America/Los_Angeles' => 'Los_Angeles (-8:00)', + 'America/Tijuana' => 'Tijuana (-8:00)', + 'America/Vancouver' => 'Vancouver (-8:00)', + 'America/Whitehorse' => 'Whitehorse (-8:00)', + 'America/Boise' => 'Boise (-7:00)', + 'America/Cambridge_Bay' => 'Cambridge_Bay (-7:00)', + 'America/Chihuahua' => 'Chihuahua (-7:00)', + 'America/Dawson_Creek' => 'Dawson_Creek (-7:00)', + 'America/Denver' => 'Denver (-7:00)', + 'America/Edmonton' => 'Edmonton (-7:00)', + 'America/Hermosillo' => 'Hermosillo (-7:00)', + 'America/Inuvik' => 'Inuvik (-7:00)', + 'America/Mazatlan' => 'Mazatlan (-7:00)', + 'America/Phoenix' => 'Phoenix (-7:00)', + 'America/Shiprock' => 'Shiprock (-7:00)', + 'America/Yellowknife' => 'Yellowknife (-7:00)', + 'America/Belize' => 'Belize (-6:00)', + 'America/Cancun' => 'Cancun (-6:00)', + 'America/Chicago' => 'Chicago (-6:00)', + 'America/Costa_Rica' => 'Costa_Rica (-6:00)', + 'America/El_Salvador' => 'El_Salvador (-6:00)', + 'America/Guatemala' => 'Guatemala (-6:00)', + 'America/Knox_IN' => 'Knox_IN (-6:00)', + 'America/Managua' => 'Managua (-6:00)', + 'America/Menominee' => 'Menominee (-6:00)', + 'America/Merida' => 'Merida (-6:00)', + 'America/Mexico_City' => 'Mexico_City (-6:00)', + 'America/Monterrey' => 'Monterrey (-6:00)', + 'America/Rainy_River' => 'Rainy_River (-6:00)', + 'America/Rankin_Inlet' => 'Rankin_Inlet (-6:00)', + 'America/Regina' => 'Regina (-6:00)', + 'America/Swift_Current' => 'Swift_Current (-6:00)', + 'America/Tegucigalpa' => 'Tegucigalpa (-6:00)', + 'America/Winnipeg' => 'Winnipeg (-6:00)', + 'America/Atikokan' => 'Atikokan (-5:00)', + 'America/Bogota' => 'Bogota (-5:00)', + 'America/Cayman' => 'Cayman (-5:00)', + 'America/Coral_Harbour' => 'Coral_Harbour (-5:00)', + 'America/Detroit' => 'Detroit (-5:00)', + 'America/Fort_Wayne' => 'Fort_Wayne (-5:00)', + 'America/Grand_Turk' => 'Grand_Turk (-5:00)', + 'America/Guayaquil' => 'Guayaquil (-5:00)', + 'America/Havana' => 'Havana (-5:00)', + 'America/Indianapolis' => 'Indianapolis (-5:00)', + 'America/Iqaluit' => 'Iqaluit (-5:00)', + 'America/Jamaica' => 'Jamaica (-5:00)', + 'America/Lima' => 'Lima (-5:00)', + 'America/Louisville' => 'Louisville (-5:00)', + 'America/Montreal' => 'Montreal (-5:00)', + 'America/Nassau' => 'Nassau (-5:00)', + 'America/New_York' => 'New_York (-5:00)', + 'America/Nipigon' => 'Nipigon (-5:00)', + 'America/Panama' => 'Panama (-5:00)', + 'America/Pangnirtung' => 'Pangnirtung (-5:00)', + 'America/Port-au-Prince' => 'Port-au-Prince (-5:00)', + 'America/Resolute' => 'Resolute (-5:00)', + 'America/Thunder_Bay' => 'Thunder_Bay (-5:00)', + 'America/Toronto' => 'Toronto (-5:00)', + 'America/Caracas' => 'Caracas (-4:-30)', + 'America/Anguilla' => 'Anguilla (-4:00)', + 'America/Antigua' => 'Antigua (-4:00)', + 'America/Aruba' => 'Aruba (-4:00)', + 'America/Asuncion' => 'Asuncion (-4:00)', + 'America/Barbados' => 'Barbados (-4:00)', + 'America/Blanc-Sablon' => 'Blanc-Sablon (-4:00)', + 'America/Boa_Vista' => 'Boa_Vista (-4:00)', + 'America/Campo_Grande' => 'Campo_Grande (-4:00)', + 'America/Cuiaba' => 'Cuiaba (-4:00)', + 'America/Curacao' => 'Curacao (-4:00)', + 'America/Dominica' => 'Dominica (-4:00)', + 'America/Eirunepe' => 'Eirunepe (-4:00)', + 'America/Glace_Bay' => 'Glace_Bay (-4:00)', + 'America/Goose_Bay' => 'Goose_Bay (-4:00)', + 'America/Grenada' => 'Grenada (-4:00)', + 'America/Guadeloupe' => 'Guadeloupe (-4:00)', + 'America/Guyana' => 'Guyana (-4:00)', + 'America/Halifax' => 'Halifax (-4:00)', + 'America/La_Paz' => 'La_Paz (-4:00)', + 'America/Manaus' => 'Manaus (-4:00)', + 'America/Marigot' => 'Marigot (-4:00)', + 'America/Martinique' => 'Martinique (-4:00)', + 'America/Moncton' => 'Moncton (-4:00)', + 'America/Montserrat' => 'Montserrat (-4:00)', + 'America/Port_of_Spain' => 'Port_of_Spain (-4:00)', + 'America/Porto_Acre' => 'Porto_Acre (-4:00)', + 'America/Porto_Velho' => 'Porto_Velho (-4:00)', + 'America/Puerto_Rico' => 'Puerto_Rico (-4:00)', + 'America/Rio_Branco' => 'Rio_Branco (-4:00)', + 'America/Santiago' => 'Santiago (-4:00)', + 'America/Santo_Domingo' => 'Santo_Domingo (-4:00)', + 'America/St_Barthelemy' => 'St_Barthelemy (-4:00)', + 'America/St_Kitts' => 'St_Kitts (-4:00)', + 'America/St_Lucia' => 'St_Lucia (-4:00)', + 'America/St_Thomas' => 'St_Thomas (-4:00)', + 'America/St_Vincent' => 'St_Vincent (-4:00)', + 'America/Thule' => 'Thule (-4:00)', + 'America/Tortola' => 'Tortola (-4:00)', + 'America/Virgin' => 'Virgin (-4:00)', + 'America/St_Johns' => 'St_Johns (-3:-30)', + 'America/Araguaina' => 'Araguaina (-3:00)', + 'America/Bahia' => 'Bahia (-3:00)', + 'America/Belem' => 'Belem (-3:00)', + 'America/Buenos_Aires' => 'Buenos_Aires (-3:00)', + 'America/Catamarca' => 'Catamarca (-3:00)', + 'America/Cayenne' => 'Cayenne (-3:00)', + 'America/Cordoba' => 'Cordoba (-3:00)', + 'America/Fortaleza' => 'Fortaleza (-3:00)', + 'America/Godthab' => 'Godthab (-3:00)', + 'America/Jujuy' => 'Jujuy (-3:00)', + 'America/Maceio' => 'Maceio (-3:00)', + 'America/Mendoza' => 'Mendoza (-3:00)', + 'America/Miquelon' => 'Miquelon (-3:00)', + 'America/Montevideo' => 'Montevideo (-3:00)', + 'America/Paramaribo' => 'Paramaribo (-3:00)', + 'America/Recife' => 'Recife (-3:00)', + 'America/Rosario' => 'Rosario (-3:00)', + 'America/Santarem' => 'Santarem (-3:00)', + 'America/Sao_Paulo' => 'Sao_Paulo (-3:00)', + 'America/Noronha' => 'Noronha (-2:00)', + 'America/Scoresbysund' => 'Scoresbysund (-1:00)', + 'America/Danmarkshavn' => 'Danmarkshavn (+0:00)', + ], + 'Canada' => [ + 'Canada/Pacific' => 'Pacific (-8:00)', + 'Canada/Yukon' => 'Yukon (-8:00)', + 'Canada/Mountain' => 'Mountain (-7:00)', + 'Canada/Central' => 'Central (-6:00)', + 'Canada/East-Saskatchewan' => 'East-Saskatchewan (-6:00)', + 'Canada/Saskatchewan' => 'Saskatchewan (-6:00)', + 'Canada/Eastern' => 'Eastern (-5:00)', + 'Canada/Atlantic' => 'Atlantic (-4:00)', + 'Canada/Newfoundland' => 'Newfoundland (-3:-30)', + ], + 'Mexico' => [ + 'Mexico/BajaNorte' => 'BajaNorte (-8:00)', + 'Mexico/BajaSur' => 'BajaSur (-7:00)', + 'Mexico/General' => 'General (-6:00)', + ], + 'Chile' => [ + 'Chile/EasterIsland' => 'EasterIsland (-6:00)', + 'Chile/Continental' => 'Continental (-4:00)', + ], + 'Antarctica' => [ + 'Antarctica/Palmer' => 'Palmer (-4:00)', + 'Antarctica/Rothera' => 'Rothera (-3:00)', + 'Antarctica/Syowa' => 'Syowa (+3:00)', + 'Antarctica/Mawson' => 'Mawson (+6:00)', + 'Antarctica/Vostok' => 'Vostok (+6:00)', + 'Antarctica/Davis' => 'Davis (+7:00)', + 'Antarctica/Casey' => 'Casey (+8:00)', + 'Antarctica/DumontDUrville' => 'DumontDUrville (+10:00)', + 'Antarctica/McMurdo' => 'McMurdo (+12:00)', + 'Antarctica/South_Pole' => 'South_Pole (+12:00)', + ], + 'Atlantic' => [ + 'Atlantic/Bermuda' => 'Bermuda (-4:00)', + 'Atlantic/Stanley' => 'Stanley (-4:00)', + 'Atlantic/South_Georgia' => 'South_Georgia (-2:00)', + 'Atlantic/Azores' => 'Azores (-1:00)', + 'Atlantic/Cape_Verde' => 'Cape_Verde (-1:00)', + 'Atlantic/Canary' => 'Canary (+0:00)', + 'Atlantic/Faeroe' => 'Faeroe (+0:00)', + 'Atlantic/Faroe' => 'Faroe (+0:00)', + 'Atlantic/Madeira' => 'Madeira (+0:00)', + 'Atlantic/Reykjavik' => 'Reykjavik (+0:00)', + 'Atlantic/St_Helena' => 'St_Helena (+0:00)', + 'Atlantic/Jan_Mayen' => 'Jan_Mayen (+1:00)', + ], + 'Brazil' => [ + 'Brazil/Acre' => 'Acre (-4:00)', + 'Brazil/West' => 'West (-4:00)', + 'Brazil/East' => 'East (-3:00)', + 'Brazil/DeNoronha' => 'DeNoronha (-2:00)', + ], + 'Africa' => [ + 'Africa/Abidjan' => 'Abidjan (+0:00)', + 'Africa/Accra' => 'Accra (+0:00)', + 'Africa/Bamako' => 'Bamako (+0:00)', + 'Africa/Banjul' => 'Banjul (+0:00)', + 'Africa/Bissau' => 'Bissau (+0:00)', + 'Africa/Casablanca' => 'Casablanca (+0:00)', + 'Africa/Conakry' => 'Conakry (+0:00)', + 'Africa/Dakar' => 'Dakar (+0:00)', + 'Africa/El_Aaiun' => 'El_Aaiun (+0:00)', + 'Africa/Freetown' => 'Freetown (+0:00)', + 'Africa/Lome' => 'Lome (+0:00)', + 'Africa/Monrovia' => 'Monrovia (+0:00)', + 'Africa/Nouakchott' => 'Nouakchott (+0:00)', + 'Africa/Ouagadougou' => 'Ouagadougou (+0:00)', + 'Africa/Sao_Tome' => 'Sao_Tome (+0:00)', + 'Africa/Timbuktu' => 'Timbuktu (+0:00)', + 'Africa/Algiers' => 'Algiers (+1:00)', + 'Africa/Bangui' => 'Bangui (+1:00)', + 'Africa/Brazzaville' => 'Brazzaville (+1:00)', + 'Africa/Ceuta' => 'Ceuta (+1:00)', + 'Africa/Douala' => 'Douala (+1:00)', + 'Africa/Kinshasa' => 'Kinshasa (+1:00)', + 'Africa/Lagos' => 'Lagos (+1:00)', + 'Africa/Libreville' => 'Libreville (+1:00)', + 'Africa/Luanda' => 'Luanda (+1:00)', + 'Africa/Malabo' => 'Malabo (+1:00)', + 'Africa/Ndjamena' => 'Ndjamena (+1:00)', + 'Africa/Niamey' => 'Niamey (+1:00)', + 'Africa/Porto-Novo' => 'Porto-Novo (+1:00)', + 'Africa/Tunis' => 'Tunis (+1:00)', + 'Africa/Windhoek' => 'Windhoek (+1:00)', + 'Africa/Blantyre' => 'Blantyre (+2:00)', + 'Africa/Bujumbura' => 'Bujumbura (+2:00)', + 'Africa/Cairo' => 'Cairo (+2:00)', + 'Africa/Gaborone' => 'Gaborone (+2:00)', + 'Africa/Harare' => 'Harare (+2:00)', + 'Africa/Johannesburg' => 'Johannesburg (+2:00)', + 'Africa/Kigali' => 'Kigali (+2:00)', + 'Africa/Lubumbashi' => 'Lubumbashi (+2:00)', + 'Africa/Lusaka' => 'Lusaka (+2:00)', + 'Africa/Maputo' => 'Maputo (+2:00)', + 'Africa/Maseru' => 'Maseru (+2:00)', + 'Africa/Mbabane' => 'Mbabane (+2:00)', + 'Africa/Tripoli' => 'Tripoli (+2:00)', + 'Africa/Addis_Ababa' => 'Addis_Ababa (+3:00)', + 'Africa/Asmara' => 'Asmara (+3:00)', + 'Africa/Asmera' => 'Asmera (+3:00)', + 'Africa/Dar_es_Salaam' => 'Dar_es_Salaam (+3:00)', + 'Africa/Djibouti' => 'Djibouti (+3:00)', + 'Africa/Kampala' => 'Kampala (+3:00)', + 'Africa/Khartoum' => 'Khartoum (+3:00)', + 'Africa/Mogadishu' => 'Mogadishu (+3:00)', + 'Africa/Nairobi' => 'Nairobi (+3:00)', + ], + 'Europe' => [ + 'Europe/Belfast' => 'Belfast (+0:00)', + 'Europe/Dublin' => 'Dublin (+0:00)', + 'Europe/Guernsey' => 'Guernsey (+0:00)', + 'Europe/Isle_of_Man' => 'Isle_of_Man (+0:00)', + 'Europe/Jersey' => 'Jersey (+0:00)', + 'Europe/Lisbon' => 'Lisbon (+0:00)', + 'Europe/London' => 'London (+0:00)', + 'Europe/Amsterdam' => 'Amsterdam (+1:00)', + 'Europe/Andorra' => 'Andorra (+1:00)', + 'Europe/Belgrade' => 'Belgrade (+1:00)', + 'Europe/Berlin' => 'Berlin (+1:00)', + 'Europe/Bratislava' => 'Bratislava (+1:00)', + 'Europe/Brussels' => 'Brussels (+1:00)', + 'Europe/Budapest' => 'Budapest (+1:00)', + 'Europe/Copenhagen' => 'Copenhagen (+1:00)', + 'Europe/Gibraltar' => 'Gibraltar (+1:00)', + 'Europe/Ljubljana' => 'Ljubljana (+1:00)', + 'Europe/Luxembourg' => 'Luxembourg (+1:00)', + 'Europe/Madrid' => 'Madrid (+1:00)', + 'Europe/Malta' => 'Malta (+1:00)', + 'Europe/Monaco' => 'Monaco (+1:00)', + 'Europe/Oslo' => 'Oslo (+1:00)', + 'Europe/Paris' => 'Paris (+1:00)', + 'Europe/Podgorica' => 'Podgorica (+1:00)', + 'Europe/Prague' => 'Prague (+1:00)', + 'Europe/Rome' => 'Rome (+1:00)', + 'Europe/San_Marino' => 'San_Marino (+1:00)', + 'Europe/Sarajevo' => 'Sarajevo (+1:00)', + 'Europe/Skopje' => 'Skopje (+1:00)', + 'Europe/Stockholm' => 'Stockholm (+1:00)', + 'Europe/Tirane' => 'Tirane (+1:00)', + 'Europe/Vaduz' => 'Vaduz (+1:00)', + 'Europe/Vatican' => 'Vatican (+1:00)', + 'Europe/Vienna' => 'Vienna (+1:00)', + 'Europe/Warsaw' => 'Warsaw (+1:00)', + 'Europe/Zagreb' => 'Zagreb (+1:00)', + 'Europe/Zurich' => 'Zurich (+1:00)', + 'Europe/Athens' => 'Athens (+2:00)', + 'Europe/Bucharest' => 'Bucharest (+2:00)', + 'Europe/Chisinau' => 'Chisinau (+2:00)', + 'Europe/Helsinki' => 'Helsinki (+2:00)', + 'Europe/Istanbul' => 'Istanbul (+2:00)', + 'Europe/Kaliningrad' => 'Kaliningrad (+2:00)', + 'Europe/Kiev' => 'Kiev (+2:00)', + 'Europe/Mariehamn' => 'Mariehamn (+2:00)', + 'Europe/Minsk' => 'Minsk (+2:00)', + 'Europe/Nicosia' => 'Nicosia (+2:00)', + 'Europe/Riga' => 'Riga (+2:00)', + 'Europe/Simferopol' => 'Simferopol (+2:00)', + 'Europe/Sofia' => 'Sofia (+2:00)', + 'Europe/Tallinn' => 'Tallinn (+2:00)', + 'Europe/Tiraspol' => 'Tiraspol (+2:00)', + 'Europe/Uzhgorod' => 'Uzhgorod (+2:00)', + 'Europe/Vilnius' => 'Vilnius (+2:00)', + 'Europe/Zaporozhye' => 'Zaporozhye (+2:00)', + 'Europe/Moscow' => 'Moscow (+3:00)', + 'Europe/Volgograd' => 'Volgograd (+3:00)', + 'Europe/Samara' => 'Samara (+4:00)', + ], + 'Arctic' => [ + 'Arctic/Longyearbyen' => 'Longyearbyen (+1:00)', + ], + 'Asia' => [ + 'Asia/Amman' => 'Amman (+2:00)', + 'Asia/Beirut' => 'Beirut (+2:00)', + 'Asia/Damascus' => 'Damascus (+2:00)', + 'Asia/Gaza' => 'Gaza (+2:00)', + 'Asia/Istanbul' => 'Istanbul (+2:00)', + 'Asia/Jerusalem' => 'Jerusalem (+2:00)', + 'Asia/Nicosia' => 'Nicosia (+2:00)', + 'Asia/Tel_Aviv' => 'Tel_Aviv (+2:00)', + 'Asia/Aden' => 'Aden (+3:00)', + 'Asia/Baghdad' => 'Baghdad (+3:00)', + 'Asia/Bahrain' => 'Bahrain (+3:00)', + 'Asia/Kuwait' => 'Kuwait (+3:00)', + 'Asia/Qatar' => 'Qatar (+3:00)', + 'Asia/Tehran' => 'Tehran (+3:30)', + 'Asia/Baku' => 'Baku (+4:00)', + 'Asia/Dubai' => 'Dubai (+4:00)', + 'Asia/Muscat' => 'Muscat (+4:00)', + 'Asia/Tbilisi' => 'Tbilisi (+4:00)', + 'Asia/Yerevan' => 'Yerevan (+4:00)', + 'Asia/Kabul' => 'Kabul (+4:30)', + 'Asia/Aqtau' => 'Aqtau (+5:00)', + 'Asia/Aqtobe' => 'Aqtobe (+5:00)', + 'Asia/Ashgabat' => 'Ashgabat (+5:00)', + 'Asia/Ashkhabad' => 'Ashkhabad (+5:00)', + 'Asia/Dushanbe' => 'Dushanbe (+5:00)', + 'Asia/Karachi' => 'Karachi (+5:00)', + 'Asia/Oral' => 'Oral (+5:00)', + 'Asia/Samarkand' => 'Samarkand (+5:00)', + 'Asia/Tashkent' => 'Tashkent (+5:00)', + 'Asia/Yekaterinburg' => 'Yekaterinburg (+5:00)', + 'Asia/Calcutta' => 'Calcutta (+5:30)', + 'Asia/Colombo' => 'Colombo (+5:30)', + 'Asia/Kolkata' => 'Kolkata (+5:30)', + 'Asia/Katmandu' => 'Katmandu (+5:45)', + 'Asia/Almaty' => 'Almaty (+6:00)', + 'Asia/Bishkek' => 'Bishkek (+6:00)', + 'Asia/Dacca' => 'Dacca (+6:00)', + 'Asia/Dhaka' => 'Dhaka (+6:00)', + 'Asia/Novosibirsk' => 'Novosibirsk (+6:00)', + 'Asia/Omsk' => 'Omsk (+6:00)', + 'Asia/Qyzylorda' => 'Qyzylorda (+6:00)', + 'Asia/Thimbu' => 'Thimbu (+6:00)', + 'Asia/Thimphu' => 'Thimphu (+6:00)', + 'Asia/Rangoon' => 'Rangoon (+6:30)', + 'Asia/Bangkok' => 'Bangkok (+7:00)', + 'Asia/Ho_Chi_Minh' => 'Ho_Chi_Minh (+7:00)', + 'Asia/Hovd' => 'Hovd (+7:00)', + 'Asia/Jakarta' => 'Jakarta (+7:00)', + 'Asia/Krasnoyarsk' => 'Krasnoyarsk (+7:00)', + 'Asia/Phnom_Penh' => 'Phnom_Penh (+7:00)', + 'Asia/Pontianak' => 'Pontianak (+7:00)', + 'Asia/Saigon' => 'Saigon (+7:00)', + 'Asia/Vientiane' => 'Vientiane (+7:00)', + 'Asia/Brunei' => 'Brunei (+8:00)', + 'Asia/Choibalsan' => 'Choibalsan (+8:00)', + 'Asia/Chongqing' => 'Chongqing (+8:00)', + 'Asia/Chungking' => 'Chungking (+8:00)', + 'Asia/Harbin' => 'Harbin (+8:00)', + 'Asia/Hong_Kong' => 'Hong_Kong (+8:00)', + 'Asia/Irkutsk' => 'Irkutsk (+8:00)', + 'Asia/Kashgar' => 'Kashgar (+8:00)', + 'Asia/Kuala_Lumpur' => 'Kuala_Lumpur (+8:00)', + 'Asia/Kuching' => 'Kuching (+8:00)', + 'Asia/Macao' => 'Macao (+8:00)', + 'Asia/Macau' => 'Macau (+8:00)', + 'Asia/Makassar' => 'Makassar (+8:00)', + 'Asia/Manila' => 'Manila (+8:00)', + 'Asia/Shanghai' => 'Shanghai (+8:00)', + 'Asia/Singapore' => 'Singapore (+8:00)', + 'Asia/Taipei' => 'Taipei (+8:00)', + 'Asia/Ujung_Pandang' => 'Ujung_Pandang (+8:00)', + 'Asia/Ulaanbaatar' => 'Ulaanbaatar (+8:00)', + 'Asia/Ulan_Bator' => 'Ulan_Bator (+8:00)', + 'Asia/Urumqi' => 'Urumqi (+8:00)', + 'Asia/Dili' => 'Dili (+9:00)', + 'Asia/Jayapura' => 'Jayapura (+9:00)', + 'Asia/Pyongyang' => 'Pyongyang (+9:00)', + 'Asia/Seoul' => 'Seoul (+9:00)', + 'Asia/Tokyo' => 'Tokyo (+9:00)', + 'Asia/Yakutsk' => 'Yakutsk (+9:00)', + 'Asia/Sakhalin' => 'Sakhalin (+10:00)', + 'Asia/Vladivostok' => 'Vladivostok (+10:00)', + 'Asia/Magadan' => 'Magadan (+11:00)', + 'Asia/Anadyr' => 'Anadyr (+12:00)', + 'Asia/Kamchatka' => 'Kamchatka (+12:00)', + ], + 'Indian' => [ + 'Indian/Antananarivo' => 'Antananarivo (+3:00)', + 'Indian/Comoro' => 'Comoro (+3:00)', + 'Indian/Mayotte' => 'Mayotte (+3:00)', + 'Indian/Mahe' => 'Mahe (+4:00)', + 'Indian/Mauritius' => 'Mauritius (+4:00)', + 'Indian/Reunion' => 'Reunion (+4:00)', + 'Indian/Kerguelen' => 'Kerguelen (+5:00)', + 'Indian/Maldives' => 'Maldives (+5:00)', + 'Indian/Chagos' => 'Chagos (+6:00)', + 'Indian/Cocos' => 'Cocos (+6:30)', + 'Indian/Christmas' => 'Christmas (+7:00)', + ], + 'Australia' => [ + 'Australia/Perth' => 'Perth (+8:00)', + 'Australia/West' => 'West (+8:00)', + 'Australia/Eucla' => 'Eucla (+8:45)', + 'Australia/Adelaide' => 'Adelaide (+9:30)', + 'Australia/Broken_Hill' => 'Broken_Hill (+9:30)', + 'Australia/Darwin' => 'Darwin (+9:30)', + 'Australia/North' => 'North (+9:30)', + 'Australia/South' => 'South (+9:30)', + 'Australia/Yancowinna' => 'Yancowinna (+9:30)', + 'Australia/ACT' => 'ACT (+10:00)', + 'Australia/Brisbane' => 'Brisbane (+10:00)', + 'Australia/Canberra' => 'Canberra (+10:00)', + 'Australia/Currie' => 'Currie (+10:00)', + 'Australia/Hobart' => 'Hobart (+10:00)', + 'Australia/Lindeman' => 'Lindeman (+10:00)', + 'Australia/Melbourne' => 'Melbourne (+10:00)', + 'Australia/NSW' => 'NSW (+10:00)', + 'Australia/Queensland' => 'Queensland (+10:00)', + 'Australia/Sydney' => 'Sydney (+10:00)', + 'Australia/Tasmania' => 'Tasmania (+10:00)', + 'Australia/Victoria' => 'Victoria (+10:00)', + 'Australia/LHI' => 'LHI (+10:30)', + 'Australia/Lord_Howe' => 'Lord_Howe (+10:30)', + ], + ]; + + public function __construct() + { + $this->framework = & get_instance(); + + $this->framework->load->model('user_model'); + + $this->framework->load->library('session'); + } + + /** + * Get all timezones to a grouped array (by continent). + * + * @return array + */ + public function to_grouped_array() + { + return $this->timezones; + } + + /** + * Convert the dates of an event to the timezone of the user. + * + * @param array $event Must contain the "start_datetime", "end_datetime" and "id_users_provider" properties. + * + * @return array + * + * @throws Exception + */ + public function convert_event_timezone($event) + { + if ( ! isset($event['start_datetime'], $event['end_datetime'], $event['id_users_provider'])) + { + throw new Exception('The provided event does not have the required properties: ' . print_r($event)); + } + + $user_timezone = $this->framework->user_model->get_user_timezone($event['id_users_provider']); + + $session_timezone = $this->get_session_timezone(); + + $event['start_datetime'] = $this->convert($event['start_datetime'], + $user_timezone, $session_timezone); + + $event['end_datetime'] = $this->convert($event['end_datetime'], + $user_timezone, $session_timezone); + + return $event; + } + + + /** + * Returns the session timezone or the default timezone as a fallback. + * + * @return string + */ + public function get_session_timezone() + { + $default_timezone = $this->get_default_timezone(); + + return $this->framework->session->has_userdata('timezone') + ? $this->framework->session->userdata('timezone') + : $default_timezone; + } + + /** + * Get the default timezone value of the current system. + * + * @return string + */ + public function get_default_timezone() + { + return 'UTC'; + } + + /** + * Convert a date time value to a new timezone. + * + * @param string $value Provide a date time value as a string (format Y-m-d H:i:s). + * @param string $from_timezone From timezone value. + * @param string $to_timezone To timezone value. + * + * @return string + * + * @throws Exception + */ + public function convert($value, $from_timezone, $to_timezone) + { + if ( ! $to_timezone) + { + return $value; + } + + $from = new DateTimeZone($from_timezone); + + $to = new DateTimeZone($to_timezone); + + $result = new DateTime($value, $from); + + $result->setTimezone($to); + + return $result->format('Y-m-d H:i:s'); + } + + /** + * Get the timezone name for the provided value. + * + * @param string $value + * + * @return string|null + */ + public function get_timezone_name($value) + { + $timezones = $this->to_array(); + + return isset($timezones[$value]) ? $timezones[$value] : NULL; + } + + /** + * Get all timezones to a flat array. + * + * @return array + */ + public function to_array() + { + return array_merge(...array_values($this->timezones)); + } +} diff --git a/src/application/libraries/index.html b/application/libraries/index.html similarity index 100% rename from src/application/libraries/index.html rename to application/libraries/index.html diff --git a/application/migrations/001_specific_calendar_sync.php b/application/migrations/001_specific_calendar_sync.php new file mode 100644 index 00000000..d7a190ae --- /dev/null +++ b/application/migrations/001_specific_calendar_sync.php @@ -0,0 +1,507 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.4.0 + * ---------------------------------------------------------------------------- */ + +/** + * Class Migration_Specific_calendar_sync + * + * Notice: This first migration got altered to include the creation of the initial database structure so that external + * SQL are not required. + * + * @property CI_DB_query_builder $db + * @property CI_DB_forge dbforge + */ +class Migration_Specific_calendar_sync extends CI_Migration { + /** + * Upgrade method. + */ + public function up() + { + $this->dbforge->add_field([ + 'id' => [ + 'type' => 'BIGINT', + 'constraint' => '20', + 'unsigned' => TRUE, + 'auto_increment' => TRUE + ], + 'book_datetime' => [ + 'type' => 'DATETIME', + 'null' => TRUE, + ], + 'start_datetime' => [ + 'type' => 'DATETIME', + 'null' => TRUE, + ], + 'end_datetime' => [ + 'type' => 'DATETIME', + 'null' => TRUE, + ], + 'notes' => [ + 'type' => 'TEXT', + 'null' => TRUE, + ], + 'hash' => [ + 'type' => 'TEXT', + 'null' => TRUE, + ], + 'is_unavailable' => [ + 'type' => 'TINYINT', + 'constraint' => '4', + 'default' => '0' + ], + 'id_users_provider' => [ + 'type' => 'BIGINT', + 'constraint' => '20', + 'unsigned' => TRUE, + 'null' => TRUE + ], + 'id_users_customer' => [ + 'type' => 'BIGINT', + 'constraint' => '20', + 'unsigned' => TRUE, + 'null' => TRUE + ], + 'id_services' => [ + 'type' => 'BIGINT', + 'constraint' => '20', + 'unsigned' => TRUE, + 'null' => TRUE + ], + 'id_google_calendar' => [ + 'type' => 'TEXT', + 'null' => TRUE + ], + ]); + $this->dbforge->add_key('id', TRUE); + $this->dbforge->add_key('id_users_provider'); + $this->dbforge->add_key('id_users_customer'); + $this->dbforge->add_key('id_services'); + $this->dbforge->create_table('appointments', TRUE, ['engine' => 'InnoDB']); + + $this->dbforge->add_field([ + 'id' => [ + 'type' => 'BIGINT', + 'constraint' => '20', + 'unsigned' => TRUE, + 'auto_increment' => TRUE + ], + 'name' => [ + 'type' => 'VARCHAR', + 'constraint' => '256', + 'null' => TRUE + ], + 'slug' => [ + 'type' => 'VARCHAR', + 'constraint' => '256', + 'null' => TRUE + ], + 'is_admin' => [ + 'type' => 'TINYINT', + 'constraint' => '4', + 'null' => TRUE + ], + 'appointments' => [ + 'type' => 'INT', + 'constraint' => '4', + 'null' => TRUE + ], + 'customers' => [ + 'type' => 'INT', + 'constraint' => '4', + 'null' => TRUE + ], + 'services' => [ + 'type' => 'INT', + 'constraint' => '4', + 'null' => TRUE + ], + 'users' => [ + 'type' => 'INT', + 'constraint' => '4', + 'null' => TRUE + ], + 'system_settings' => [ + 'type' => 'INT', + 'constraint' => '4', + 'null' => TRUE + ], + 'user_settings' => [ + 'type' => 'INT', + 'constraint' => '4', + 'null' => TRUE + ], + ]); + $this->dbforge->add_key('id', TRUE); + $this->dbforge->create_table('roles', TRUE, ['engine' => 'InnoDB']); + + $this->dbforge->add_field([ + 'id_users_secretary' => [ + 'type' => 'BIGINT', + 'constraint' => '20', + 'unsigned' => TRUE, + ], + 'id_users_provider' => [ + 'type' => 'BIGINT', + 'constraint' => '20', + 'unsigned' => TRUE, + ] + ]); + $this->dbforge->add_key('id_users_secretary', TRUE); + $this->dbforge->add_key('id_users_provider', TRUE); + $this->dbforge->create_table('secretaries_providers', TRUE, ['engine' => 'InnoDB']); + + $this->dbforge->add_field([ + 'id' => [ + 'type' => 'BIGINT', + 'constraint' => '20', + 'unsigned' => TRUE, + 'auto_increment' => TRUE + ], + 'name' => [ + 'type' => 'VARCHAR', + 'constraint' => '256', + 'null' => TRUE + ], + 'duration' => [ + 'type' => 'INT', + 'constraint' => '11', + 'null' => TRUE + ], + 'price' => [ + 'type' => 'DECIMAL', + 'constraint' => '10,2', + 'null' => TRUE + ], + 'currency' => [ + 'type' => 'VARCHAR', + 'constraint' => '32', + 'null' => TRUE + ], + 'description' => [ + 'type' => 'TEXT', + 'null' => TRUE + ], + 'id_service_categories' => [ + 'type' => 'BIGINT', + 'constraint' => '20', + 'unsigned' => TRUE, + 'null' => TRUE + ], + ]); + $this->dbforge->add_key('id', TRUE); + $this->dbforge->add_key('id_service_categories'); + $this->dbforge->create_table('services', TRUE, ['engine' => 'InnoDB']); + + $this->dbforge->add_field([ + 'id_users' => [ + 'type' => 'BIGINT', + 'constraint' => '20', + 'unsigned' => TRUE, + ], + 'id_services' => [ + 'type' => 'BIGINT', + 'constraint' => '20', + 'unsigned' => TRUE, + ] + ]); + $this->dbforge->add_key('id_users', TRUE); + $this->dbforge->add_key('id_services', TRUE); + $this->dbforge->create_table('services_providers', TRUE, ['engine' => 'InnoDB']); + + $this->dbforge->add_field([ + 'id' => [ + 'type' => 'BIGINT', + 'constraint' => '20', + 'unsigned' => TRUE, + 'auto_increment' => TRUE + ], + 'name' => [ + 'type' => 'VARCHAR', + 'constraint' => '256', + 'null' => TRUE + ], + 'description' => [ + 'type' => 'TEXT', + 'null' => TRUE + ], + ]); + $this->dbforge->add_key('id', TRUE); + $this->dbforge->add_key('id_service_categories'); + $this->dbforge->create_table('service_categories', TRUE, ['engine' => 'InnoDB']); + + $this->dbforge->add_field([ + 'id' => [ + 'type' => 'BIGINT', + 'constraint' => '20', + 'unsigned' => TRUE, + 'auto_increment' => TRUE + ], + 'name' => [ + 'type' => 'VARCHAR', + 'constraint' => '512', + 'null' => TRUE + ], + 'value' => [ + 'type' => 'LONGTEXT', + 'null' => TRUE + ], + ]); + $this->dbforge->add_key('id', TRUE); + $this->dbforge->create_table('settings', TRUE, ['engine' => 'InnoDB']); + + $this->dbforge->add_field([ + 'id' => [ + 'type' => 'BIGINT', + 'constraint' => '20', + 'unsigned' => TRUE, + 'auto_increment' => TRUE + ], + 'first_name' => [ + 'type' => 'VARCHAR', + 'constraint' => '256', + 'null' => TRUE + ], + 'last_name' => [ + 'type' => 'VARCHAR', + 'constraint' => '512', + 'null' => TRUE + ], + 'email' => [ + 'type' => 'VARCHAR', + 'constraint' => '512', + 'null' => TRUE + ], + 'mobile_number' => [ + 'type' => 'VARCHAR', + 'constraint' => '128', + 'null' => TRUE + ], + 'phone_number' => [ + 'type' => 'VARCHAR', + 'constraint' => '128', + 'null' => TRUE + ], + 'address' => [ + 'type' => 'VARCHAR', + 'constraint' => '256', + 'null' => TRUE + ], + 'city' => [ + 'type' => 'VARCHAR', + 'constraint' => '256', + 'null' => TRUE + ], + 'state' => [ + 'type' => 'VARCHAR', + 'constraint' => '128', + 'null' => TRUE + ], + 'zip_code' => [ + 'type' => 'VARCHAR', + 'constraint' => '64', + 'null' => TRUE + ], + 'notes' => [ + 'type' => 'TEXT', + 'null' => TRUE + ], + 'id_roles' => [ + 'type' => 'BIGINT', + 'constraint' => '20', + 'unsigned' => TRUE + ], + ]); + $this->dbforge->add_key('id', TRUE); + $this->dbforge->add_key('id_roles'); + $this->dbforge->create_table('users', TRUE, ['engine' => 'InnoDB']); + + $this->dbforge->add_field([ + 'id_users' => [ + 'type' => 'BIGINT', + 'constraint' => '20', + 'unsigned' => TRUE, + ], + 'username' => [ + 'type' => 'VARCHAR', + 'constraint' => '256', + 'null' => TRUE + ], + 'password' => [ + 'type' => 'VARCHAR', + 'constraint' => '512', + 'null' => TRUE + ], + 'salt' => [ + 'type' => 'VARCHAR', + 'constraint' => '512', + 'null' => TRUE + ], + 'working_plan' => [ + 'type' => 'TEXT', + 'null' => TRUE + ], + 'notifications' => [ + 'type' => 'TINYINT', + 'constraint' => '4', + 'null' => TRUE + ], + 'google_sync' => [ + 'type' => 'TINYINT', + 'constraint' => '4', + 'null' => TRUE + ], + 'google_token' => [ + 'type' => 'TEXT', + 'null' => TRUE + ], + 'google_calendar' => [ + 'type' => 'VARCHAR', + 'constraint' => '128', + 'null' => TRUE + ], + 'sync_past_days' => [ + 'type' => 'INT', + 'constraint' => '11', + 'null' => TRUE, + 'default' => '5' + ], + 'sync_future_days' => [ + 'type' => 'INT', + 'constraint' => '11', + 'null' => TRUE, + 'default' => '5' + ], + ]); + $this->dbforge->add_key('id_users', TRUE); + $this->dbforge->create_table('user_settings', TRUE, ['engine' => 'InnoDB']); + + $this->db->query(' + ALTER TABLE `' . $this->db->dbprefix('appointments') . '` + ADD CONSTRAINT `' . $this->db->dbprefix('appointments') . '_ibfk_2` FOREIGN KEY (`id_users_customer`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + ADD CONSTRAINT `' . $this->db->dbprefix('appointments') . '_ibfk_3` FOREIGN KEY (`id_services`) REFERENCES `' . $this->db->dbprefix('services') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + ADD CONSTRAINT `' . $this->db->dbprefix('appointments') . '_ibfk_4` FOREIGN KEY (`id_users_provider`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE; + '); + + $this->db->query(' + ALTER TABLE `' . $this->db->dbprefix('secretaries_providers') . '` + ADD CONSTRAINT `fk_' . $this->db->dbprefix('secretaries_providers') . '_1` FOREIGN KEY (`id_users_secretary`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + ADD CONSTRAINT `fk_' . $this->db->dbprefix('secretaries_providers') . '_2` FOREIGN KEY (`id_users_provider`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE; + '); + + $this->db->query(' + ALTER TABLE `' . $this->db->dbprefix('services') . '` + ADD CONSTRAINT `' . $this->db->dbprefix('services') . '_ibfk_1` FOREIGN KEY (`id_service_categories`) REFERENCES `' . $this->db->dbprefix('service_categories') . '` (`id`) ON DELETE SET NULL ON UPDATE CASCADE; + '); + + $this->db->query(' + ALTER TABLE `' . $this->db->dbprefix('services_providers') . '` + ADD CONSTRAINT `' . $this->db->dbprefix('services_providers') . '_ibfk_1` FOREIGN KEY (`id_users`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + ADD CONSTRAINT `' . $this->db->dbprefix('services_providers') . '_ibfk_2` FOREIGN KEY (`id_services`) REFERENCES `' . $this->db->dbprefix('services') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE; + '); + + $this->db->query(' + ALTER TABLE `' . $this->db->dbprefix('users') . '` + ADD CONSTRAINT `' . $this->db->dbprefix('users') . '_ibfk_1` FOREIGN KEY (`id_roles`) REFERENCES `' . $this->db->dbprefix('roles') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE; + '); + + $this->db->query(' + ALTER TABLE `' . $this->db->dbprefix('user_settings') . '` + ADD CONSTRAINT `' . $this->db->dbprefix('user_settings') . '_ibfk_1` FOREIGN KEY (`id_users`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE; + + '); + + $this->db->insert('roles', [ + 'name' => 'Administrator', + 'slug' => 'admin', + 'is_admin' => TRUE, + 'appointments' => 15, + 'customers' => 15, + 'services' => 15, + 'users' => 15, + 'system_settings' => 15, + 'user_settings' => 15, + ]); + + $this->db->insert('roles', [ + 'name' => 'Provider', + 'slug' => 'provider', + 'is_admin' => FALSE, + 'appointments' => 15, + 'customers' => 15, + 'services' => 0, + 'users' => 0, + 'system_settings' => 0, + 'user_settings' => 15, + ]); + + $this->db->insert('roles', [ + 'name' => 'Customer', + 'slug' => 'customer', + 'is_admin' => FALSE, + 'appointments' => 0, + 'customers' => 0, + 'services' => 0, + 'users' => 0, + 'system_settings' => 0, + 'user_settings' => 0, + ]); + + $this->db->insert('roles', [ + 'name' => 'Secretary', + 'slug' => 'secretary', + 'is_admin' => FALSE, + 'appointments' => 15, + 'customers' => 15, + 'services' => 0, + 'users' => 0, + 'system_settings' => 0, + 'user_settings' => 15, + ]); + + $this->db->insert('settings', [ + 'name' => 'company_working_plan', + 'value' => '{"monday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"tuesday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"wednesday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"thursday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"friday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"saturday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]},"sunday":{"start":"09:00","end":"18:00","breaks":[{"start":"11:20","end":"11:30"},{"start":"14:30","end":"15:00"}]}}' + ]); + + $this->db->insert('settings', [ + 'name' => 'book_advance_timeout', + 'value' => '30' + ]); + } + + /** + * Downgrade method. + */ + public function down() + { + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('appointments') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('appointments') . '_ibfk_2`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('appointments') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('appointments') . '_ibfk_3`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('appointments') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('appointments') . '_ibfk_4`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('secretaries_providers') . '` DROP FOREIGN KEY `fk_' . $this->db->dbprefix('secretaries_providers') . '_1`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('secretaries_providers') . '` DROP FOREIGN KEY `fk_' . $this->db->dbprefix('secretaries_providers') . '_2`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('services_providers') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('services_providers') . '_ibfk_1`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('services_providers') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('services_providers') . '_ibfk_2`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('services') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('services') . '_ibfk_1`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('users') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('users') . '_ibfk_1`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('user_settings') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('user_settings') . '_ibfk_1`'); + + $this->dbforge->drop_table('appointments'); + $this->dbforge->drop_table('roles'); + $this->dbforge->drop_table('secretaries_providers'); + $this->dbforge->drop_table('services'); + $this->dbforge->drop_table('service_categories'); + $this->dbforge->drop_table('services_providers'); + $this->dbforge->drop_table('settings'); + $this->dbforge->drop_table('user_settings'); + $this->dbforge->drop_table('users'); + } +} diff --git a/application/migrations/002_add_google_analytics_setting.php b/application/migrations/002_add_google_analytics_setting.php new file mode 100644 index 00000000..e39402c8 --- /dev/null +++ b/application/migrations/002_add_google_analytics_setting.php @@ -0,0 +1,43 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.1.0 + * ---------------------------------------------------------------------------- */ + +/** + * Class Migration_Add_google_analytics_setting + * + * @property CI_DB_query_builder $db + * @property CI_DB_forge dbforge + */ +class Migration_Add_google_analytics_setting extends CI_Migration { + /** + * Upgrade method. + * + * @throws Exception + */ + public function up() + { + $this->db->insert('settings', [ + 'name' => 'google_analytics_code', + 'value' => '' + ]); + } + + /** + * Downgrade method. + * + * @throws Exception + */ + public function down() + { + $this->db->delete('settings', ['name' => 'google_analytics_code']); + } +} diff --git a/application/migrations/003_add_customer_notifications_setting.php b/application/migrations/003_add_customer_notifications_setting.php new file mode 100644 index 00000000..a90d33b5 --- /dev/null +++ b/application/migrations/003_add_customer_notifications_setting.php @@ -0,0 +1,43 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.1.0 + * ---------------------------------------------------------------------------- */ + +/** + * Class Migration_Add_customer_notifications_setting + * + * @property CI_DB_query_builder $db + * @property CI_DB_forge dbforge + */ +class Migration_Add_customer_notifications_setting extends CI_Migration { + /** + * Upgrade method. + * + * @throws Exception + */ + public function up() + { + $this->db->insert('settings', [ + 'name' => 'customer_notifications', + 'value' => '1' + ]); + } + + /** + * Downgrade method. + * + * @throws Exception + */ + public function down() + { + $this->db->delete('settings', ['name' => 'customer_notifications']); + } +} diff --git a/application/migrations/004_add_date_format_setting.php b/application/migrations/004_add_date_format_setting.php new file mode 100644 index 00000000..5dd22026 --- /dev/null +++ b/application/migrations/004_add_date_format_setting.php @@ -0,0 +1,43 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.1.0 + * ---------------------------------------------------------------------------- */ + +/** + * Class Migration_Add_date_format_setting + * + * @property CI_DB_query_builder $db + * @property CI_DB_forge dbforge + */ +class Migration_Add_date_format_setting extends CI_Migration { + /** + * Upgrade method. + * + * @throws Exception + */ + public function up() + { + $this->db->insert('settings', [ + 'name' => 'date_format', + 'value' => 'DMY' + ]); + } + + /** + * Downgrade method. + * + * @throws Exception + */ + public function down() + { + $this->db->delete('settings', ['name' => 'date_format']); + } +} diff --git a/application/migrations/005_add_require_captcha_setting.php b/application/migrations/005_add_require_captcha_setting.php new file mode 100644 index 00000000..84867be8 --- /dev/null +++ b/application/migrations/005_add_require_captcha_setting.php @@ -0,0 +1,43 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.1.0 + * ---------------------------------------------------------------------------- */ + +/** + * Class Migration_Add_require_captcha_setting + * + * @property CI_DB_query_builder $db + * @property CI_DB_forge dbforge + */ +class Migration_Add_require_captcha_setting extends CI_Migration { + /** + * Upgrade method. + * + * @throws Exception + */ + public function up() + { + $this->db->insert('settings', [ + 'name' => 'require_captcha', + 'value' => '0' + ]); + } + + /** + * Downgrade method. + * + * @throws Exception + */ + public function down() + { + $this->db->delete('settings', ['name' => 'require_captcha']); + } +} diff --git a/application/migrations/006_add_calendar_view_setting.php b/application/migrations/006_add_calendar_view_setting.php new file mode 100644 index 00000000..e7ad51f5 --- /dev/null +++ b/application/migrations/006_add_calendar_view_setting.php @@ -0,0 +1,52 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.2.0 + * ---------------------------------------------------------------------------- */ + +/** + * Class Migration_Add_calendar_view_setting + * + * @property CI_DB_query_builder $db + * @property CI_DB_forge dbforge + */ +class Migration_Add_calendar_view_setting extends CI_Migration { + /** + * Upgrade method. + */ + public function up() + { + if ( ! $this->db->field_exists('calendar_view', 'user_settings')) + { + $fields = [ + 'calendar_view' => [ + 'type' => 'VARCHAR', + 'constraint' => '32', + 'default' => 'default' + ] + ]; + + $this->dbforge->add_column('user_settings', $fields); + + $this->db->update('user_settings', ['calendar_view' => 'default']); + } + } + + /** + * Downgrade method. + */ + public function down() + { + if ($this->db->field_exists('calendar_view', 'user_settings')) + { + $this->dbforge->drop_column('user_settings', 'calendar_view'); + } + } +} diff --git a/application/migrations/007_add_service_availabilities_type.php b/application/migrations/007_add_service_availabilities_type.php new file mode 100644 index 00000000..14d824ec --- /dev/null +++ b/application/migrations/007_add_service_availabilities_type.php @@ -0,0 +1,53 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.2.0 + * ---------------------------------------------------------------------------- */ + +/** + * Class Migration_Add_service_availabilities_type + * + * @property CI_DB_query_builder $db + * @property CI_DB_forge dbforge + */ +class Migration_Add_service_availabilities_type extends CI_Migration { + /** + * Upgrade method. + */ + public function up() + { + if ( ! $this->db->field_exists('availabilities_type', 'services')) + { + $fields = [ + 'availabilities_type' => [ + 'type' => 'VARCHAR', + 'constraint' => '32', + 'default' => 'flexible', + 'after' => 'description' + ] + ]; + + $this->dbforge->add_column('services', $fields); + + $this->db->update('services', ['availabilities_type' => 'flexible']); + } + } + + /** + * Downgrade method. + */ + public function down() + { + if ($this->db->field_exists('availabilities_type', 'services')) + { + $this->dbforge->drop_column('services', 'availabilities_type'); + } + } +} diff --git a/application/migrations/008_add_service_attendants_number.php b/application/migrations/008_add_service_attendants_number.php new file mode 100644 index 00000000..728abcb9 --- /dev/null +++ b/application/migrations/008_add_service_attendants_number.php @@ -0,0 +1,51 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.2.0 + * ---------------------------------------------------------------------------- */ + +/** + * Class Migration_Add_service_attendants_number + * + * @property CI_DB_query_builder $db + * @property CI_DB_forge dbforge + */ +class Migration_Add_service_attendants_number extends CI_Migration { + /** + * Upgrade method. + */ + public function up() + { + if ( ! $this->db->field_exists('attendants_number', 'services')) + { + $fields = [ + 'attendants_number' => [ + 'type' => 'INT', + 'constraint' => '11', + 'default' => '1', + 'after' => 'availabilities_type' + ] + ]; + + $this->dbforge->add_column('services', $fields); + } + } + + /** + * Downgrade method. + */ + public function down() + { + if ($this->db->field_exists('attendants_number', 'services')) + { + $this->dbforge->drop_column('services', 'attendants_number'); + } + } +} diff --git a/application/migrations/009_change_column_types.php b/application/migrations/009_change_column_types.php new file mode 100644 index 00000000..05b8bbca --- /dev/null +++ b/application/migrations/009_change_column_types.php @@ -0,0 +1,445 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.3.0 + * ---------------------------------------------------------------------------- */ + +/** + * Class Migration_Change_column_types + * + * @property CI_DB_query_builder $db + * @property CI_DB_forge dbforge + */ +class Migration_Change_column_types extends CI_Migration { + /** + * Upgrade method. + */ + public function up() + { + // Drop table constraints. + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('appointments') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('appointments') . '_ibfk_2`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('appointments') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('appointments') . '_ibfk_3`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('appointments') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('appointments') . '_ibfk_4`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('secretaries_providers') . '` DROP FOREIGN KEY `fk_' . $this->db->dbprefix('secretaries_providers') . '_1`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('secretaries_providers') . '` DROP FOREIGN KEY `fk_' . $this->db->dbprefix('secretaries_providers') . '_2`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('services_providers') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('services_providers') . '_ibfk_1`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('services_providers') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('services_providers') . '_ibfk_2`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('services') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('services') . '_ibfk_1`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('users') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('users') . '_ibfk_1`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('user_settings') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('user_settings') . '_ibfk_1`'); + + // Appointments + $fields = [ + 'id' => [ + 'name' => 'id', + 'type' => 'int', + 'constraint' => '11', + 'auto_increment' => TRUE + ], + 'id_users_provider' => [ + 'name' => 'id_users_provider', + 'type' => 'int', + 'constraint' => '11' + ], + 'id_users_customer' => [ + 'name' => 'id_users_customer', + 'type' => 'int', + 'constraint' => '11' + ], + 'id_services' => [ + 'name' => 'id_services', + 'type' => 'int', + 'constraint' => '11' + ] + ]; + + $this->dbforge->modify_column('appointments', $fields); + + // Roles + $fields = [ + 'id' => [ + 'name' => 'id', + 'type' => 'int', + 'constraint' => '11', + 'auto_increment' => TRUE + ], + 'appointments' => [ + 'name' => 'appointments', + 'type' => 'int', + 'constraint' => '11' + ], + 'customers' => [ + 'name' => 'customers', + 'type' => 'int', + 'constraint' => '11' + ], + 'services' => [ + 'name' => 'services', + 'type' => 'int', + 'constraint' => '11' + ], + 'users' => [ + 'name' => 'users', + 'type' => 'int', + 'constraint' => '11' + ], + 'system_settings' => [ + 'name' => 'system_settings', + 'type' => 'int', + 'constraint' => '11' + ], + 'user_settings' => [ + 'name' => 'user_settings', + 'type' => 'int', + 'constraint' => '11' + ] + ]; + + $this->dbforge->modify_column('roles', $fields); + + // Secretary Provider + $fields = [ + 'id_users_secretary' => [ + 'name' => 'id_users_secretary', + 'type' => 'int', + 'constraint' => '11' + ], + 'id_users_provider' => [ + 'name' => 'id_users_provider', + 'type' => 'int', + 'constraint' => '11' + ] + ]; + + $this->dbforge->modify_column('secretaries_providers', $fields); + + // Services + $fields = [ + 'id' => [ + 'name' => 'id', + 'type' => 'int', + 'constraint' => '11', + 'auto_increment' => TRUE + ], + 'id_service_categories' => [ + 'name' => 'id_service_categories', + 'type' => 'int', + 'constraint' => '11' + ] + ]; + + $this->dbforge->modify_column('services', $fields); + + // Service Providers + $fields = [ + 'id_users' => [ + 'name' => 'id_users', + 'type' => 'int', + 'constraint' => '11' + ], + 'id_services' => [ + 'name' => 'id_services', + 'type' => 'int', + 'constraint' => '11' + ] + ]; + + $this->dbforge->modify_column('services_providers', $fields); + + // Service Categories + $fields = [ + 'id' => [ + 'name' => 'id', + 'type' => 'int', + 'constraint' => '11', + 'auto_increment' => TRUE + ] + ]; + + $this->dbforge->modify_column('service_categories', $fields); + + // Settings + $fields = [ + 'id' => [ + 'name' => 'id', + 'type' => 'int', + 'constraint' => '11', + 'auto_increment' => TRUE + ] + ]; + + $this->dbforge->modify_column('settings', $fields); + + // Users + $fields = [ + 'id' => [ + 'name' => 'id', + 'type' => 'int', + 'constraint' => '11', + 'auto_increment' => TRUE + ], + 'id_roles' => [ + 'name' => 'id_roles', + 'type' => 'int', + 'constraint' => '11' + ] + ]; + + $this->dbforge->modify_column('users', $fields); + + // Users Settings + $fields = [ + 'id_users' => [ + 'name' => 'id_users', + 'type' => 'int', + 'constraint' => '11' + ] + ]; + + $this->dbforge->modify_column('user_settings', $fields); + + // Add table constraints again. + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('appointments') . '` + ADD CONSTRAINT `' . $this->db->dbprefix('appointments') . '_ibfk_2` FOREIGN KEY (`id_users_customer`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + ADD CONSTRAINT `' . $this->db->dbprefix('appointments') . '_ibfk_3` FOREIGN KEY (`id_services`) REFERENCES `' . $this->db->dbprefix('services') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + ADD CONSTRAINT `' . $this->db->dbprefix('appointments') . '_ibfk_4` FOREIGN KEY (`id_users_provider`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE'); + + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('secretaries_providers') . '` + ADD CONSTRAINT `fk_' . $this->db->dbprefix('secretaries_providers') . '_1` FOREIGN KEY (`id_users_secretary`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + ADD CONSTRAINT `fk_' . $this->db->dbprefix('secretaries_providers') . '_2` FOREIGN KEY (`id_users_provider`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE'); + + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('services') . '` + ADD CONSTRAINT `' . $this->db->dbprefix('services') . '_ibfk_1` FOREIGN KEY (`id_service_categories`) REFERENCES `' . $this->db->dbprefix('service_categories') . '` (`id`) ON DELETE SET NULL ON UPDATE CASCADE'); + + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('services_providers') . '` + ADD CONSTRAINT `' . $this->db->dbprefix('services_providers') . '_ibfk_1` FOREIGN KEY (`id_users`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + ADD CONSTRAINT `' . $this->db->dbprefix('services_providers') . '_ibfk_2` FOREIGN KEY (`id_services`) REFERENCES `' . $this->db->dbprefix('services') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE'); + + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('users') . '` + ADD CONSTRAINT `' . $this->db->dbprefix('users') . '_ibfk_1` FOREIGN KEY (`id_roles`) REFERENCES `' . $this->db->dbprefix('roles') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE'); + + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('user_settings') . '` + ADD CONSTRAINT `' . $this->db->dbprefix('user_settings') . '_ibfk_1` FOREIGN KEY (`id_users`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE'); + + // Change charset of ' . $this->db->dbprefix('secretaries_providers') . ' table for databases created with EA! 1.2.1 version + $this->db->query('ALTER TABLE ' . $this->db->dbprefix('secretaries_providers') . ' CONVERT TO CHARACTER SET utf8'); + } + + /** + * Downgrade method. + */ + public function down() + { + // Drop table constraints. + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('appointments') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('appointments') . '_ibfk_2`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('appointments') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('appointments') . '_ibfk_3`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('appointments') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('appointments') . '_ibfk_4`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('secretaries_providers') . '` DROP FOREIGN KEY `fk_' . $this->db->dbprefix('secretaries_providers') . '_1`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('secretaries_providers') . '` DROP FOREIGN KEY `fk_' . $this->db->dbprefix('secretaries_providers') . '_2`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('services_providers') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('services_providers') . '_ibfk_1`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('services_providers') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('services_providers') . '_ibfk_2`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('services') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('services') . '_ibfk_1`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('users') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('users') . '_ibfk_1`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('user_settings') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('user_settings') . '_ibfk_1`'); + + // Appointments + $fields = [ + 'id' => [ + 'name' => 'id', + 'type' => 'bigint', + 'constraint' => '20', + 'auto_increment' => TRUE + ], + 'id_users_provider' => [ + 'name' => 'id_users_provider', + 'type' => 'bigint', + 'constraint' => '20' + ], + 'id_users_customer' => [ + 'name' => 'id_users_customer', + 'type' => 'bigint', + 'constraint' => '20' + ], + 'id_services' => [ + 'name' => 'id_services', + 'type' => 'bigint', + 'constraint' => '20' + ] + ]; + + $this->dbforge->modify_column('appointments', $fields); + + // Roles + $fields = [ + 'id' => [ + 'name' => 'id', + 'type' => 'bigint', + 'constraint' => '20', + 'auto_increment' => TRUE + ], + 'appointments' => [ + 'name' => 'appointments', + 'type' => 'bigint', + 'constraint' => '20' + ], + 'customers' => [ + 'name' => 'customers', + 'type' => 'bigint', + 'constraint' => '20' + ], + 'services' => [ + 'name' => 'services', + 'type' => 'bigint', + 'constraint' => '20' + ], + 'users' => [ + 'name' => 'users', + 'type' => 'bigint', + 'constraint' => '20' + ], + 'system_settings' => [ + 'name' => 'system_settings', + 'type' => 'bigint', + 'constraint' => '20' + ], + 'user_settings' => [ + 'name' => 'user_settings', + 'type' => 'bigint', + 'constraint' => '20' + ] + ]; + + $this->dbforge->modify_column('roles', $fields); + + // Secretary Provider + $fields = [ + 'id_users_secretary' => [ + 'name' => 'id_users_secretary', + 'type' => 'bigint', + 'constraint' => '20' + ], + 'id_users_provider' => [ + 'name' => 'id_users_provider', + 'type' => 'bigint', + 'constraint' => '20' + ] + ]; + + $this->dbforge->modify_column('secretaries_providers', $fields); + + // Services + $fields = [ + 'id' => [ + 'name' => 'id', + 'type' => 'bigint', + 'constraint' => '20', + 'auto_increment' => TRUE + ], + 'id_service_categories' => [ + 'name' => 'id_service_categories', + 'type' => 'bigint', + 'constraint' => '20' + ] + ]; + + $this->dbforge->modify_column('services', $fields); + + // Service Providers + $fields = [ + 'id_users' => [ + 'name' => 'id_users', + 'type' => 'bigint', + 'constraint' => '20' + ], + 'id_services' => [ + 'name' => 'id_services', + 'type' => 'bigint', + 'constraint' => '20' + ] + ]; + + $this->dbforge->modify_column('services_providers', $fields); + + // Service Categories + $fields = [ + 'id' => [ + 'name' => 'id', + 'type' => 'bigint', + 'constraint' => '20', + 'auto_increment' => TRUE + ] + ]; + + $this->dbforge->modify_column('service_categories', $fields); + + // Settings + $fields = [ + 'id' => [ + 'name' => 'id', + 'type' => 'bigint', + 'constraint' => '20', + 'auto_increment' => TRUE + ] + ]; + + $this->dbforge->modify_column('settings', $fields); + + // Users + $fields = [ + 'id' => [ + 'name' => 'id', + 'type' => 'bigint', + 'constraint' => '20', + 'auto_increment' => TRUE + ], + 'id_roles' => [ + 'name' => 'id_roles', + 'type' => 'bigint', + 'constraint' => '20' + ] + ]; + + $this->dbforge->modify_column('users', $fields); + + // Users Settings + $fields = [ + 'id_users' => [ + 'name' => 'id_users', + 'type' => 'bigint', + 'constraint' => '20' + ] + ]; + + $this->dbforge->modify_column('user_settings', $fields); + + // Add database constraints. + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('appointments') . '` + ADD CONSTRAINT `' . $this->db->dbprefix('appointments') . '_ibfk_2` FOREIGN KEY (`id_users_customer`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + ADD CONSTRAINT `' . $this->db->dbprefix('appointments') . '_ibfk_3` FOREIGN KEY (`id_services`) REFERENCES `' . $this->db->dbprefix('services') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + ADD CONSTRAINT `' . $this->db->dbprefix('appointments') . '_ibfk_4` FOREIGN KEY (`id_users_provider`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE'); + + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('secretaries_providers') . '` + ADD CONSTRAINT `fk_' . $this->db->dbprefix('secretaries_providers') . '_1` FOREIGN KEY (`id_users_secretary`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + ADD CONSTRAINT `fk_' . $this->db->dbprefix('secretaries_providers') . '_2` FOREIGN KEY (`id_users_provider`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE'); + + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('services') . '` + ADD CONSTRAINT `' . $this->db->dbprefix('services') . '_ibfk_1` FOREIGN KEY (`id_service_categories`) REFERENCES `' . $this->db->dbprefix('service_categories') . '` (`id`) ON DELETE SET NULL ON UPDATE CASCADE'); + + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('services_providers') . '` + ADD CONSTRAINT `' . $this->db->dbprefix('services_providers') . '_ibfk_1` FOREIGN KEY (`id_users`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + ADD CONSTRAINT `' . $this->db->dbprefix('services_providers') . '_ibfk_2` FOREIGN KEY (`id_services`) REFERENCES `' . $this->db->dbprefix('services') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE'); + + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('users') . '` + ADD CONSTRAINT `' . $this->db->dbprefix('users') . '_ibfk_1` FOREIGN KEY (`id_roles`) REFERENCES `' . $this->db->dbprefix('roles') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE'); + + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('user_settings') . '` + ADD CONSTRAINT `' . $this->db->dbprefix('user_settings') . '_ibfk_1` FOREIGN KEY (`id_users`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE'); + } +} diff --git a/application/migrations/010_add_time_format_setting.php b/application/migrations/010_add_time_format_setting.php new file mode 100644 index 00000000..e7f09463 --- /dev/null +++ b/application/migrations/010_add_time_format_setting.php @@ -0,0 +1,39 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.3.0 + * ---------------------------------------------------------------------------- */ + +/** + * Class Migration_Add_time_format_setting + * + * @property CI_DB_query_builder $db + * @property CI_DB_forge dbforge + */ +class Migration_Add_time_format_setting extends CI_Migration { + /** + * Upgrade method. + */ + public function up() + { + $this->db->insert('settings', [ + 'name' => 'time_format', + 'value' => 'regular' + ]); + } + + /** + * Downgrade method. + */ + public function down() + { + $this->db->delete('settings', ['name' => 'time_format']); + } +} diff --git a/application/migrations/011_remove_prefix_from_fkey_constraints.php b/application/migrations/011_remove_prefix_from_fkey_constraints.php new file mode 100644 index 00000000..92a8f499 --- /dev/null +++ b/application/migrations/011_remove_prefix_from_fkey_constraints.php @@ -0,0 +1,122 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.3.0 + * ---------------------------------------------------------------------------- */ + +/** + * Class Migration_Remove_prefix_from_foreign_keys + * + * @property CI_DB_query_builder $db + * @property CI_DB_forge dbforge + */ +class Migration_Remove_prefix_from_fkey_constraints extends CI_Migration { + /** + * Upgrade method. + */ + public function up() + { + // Drop table constraints. + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('appointments') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('appointments') . '_ibfk_2`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('appointments') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('appointments') . '_ibfk_3`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('appointments') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('appointments') . '_ibfk_4`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('secretaries_providers') . '` DROP FOREIGN KEY `fk_' . $this->db->dbprefix('secretaries_providers') . '_1`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('secretaries_providers') . '` DROP FOREIGN KEY `fk_' . $this->db->dbprefix('secretaries_providers') . '_2`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('services_providers') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('services_providers') . '_ibfk_1`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('services_providers') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('services_providers') . '_ibfk_2`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('services') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('services') . '_ibfk_1`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('users') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('users') . '_ibfk_1`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('user_settings') . '` DROP FOREIGN KEY `' . $this->db->dbprefix('user_settings') . '_ibfk_1`'); + + // Add table constraints again without the "ea" prefix. + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('appointments') . '` + ADD CONSTRAINT `appointments_users_customer` FOREIGN KEY (`id_users_customer`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) + ON DELETE CASCADE + ON UPDATE CASCADE, + ADD CONSTRAINT `appointments_services` FOREIGN KEY (`id_services`) REFERENCES `' . $this->db->dbprefix('services') . '` (`id`) + ON DELETE CASCADE + ON UPDATE CASCADE, + ADD CONSTRAINT `appointments_users_provider` FOREIGN KEY (`id_users_provider`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) + ON DELETE CASCADE + ON UPDATE CASCADE'); + + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('secretaries_providers') . '` + ADD CONSTRAINT `secretaries_users_secretary` FOREIGN KEY (`id_users_secretary`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) + ON DELETE CASCADE + ON UPDATE CASCADE, + ADD CONSTRAINT `secretaries_users_provider` FOREIGN KEY (`id_users_provider`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) + ON DELETE CASCADE + ON UPDATE CASCADE'); + + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('services') . '` + ADD CONSTRAINT `services_service_categories` FOREIGN KEY (`id_service_categories`) REFERENCES `' . $this->db->dbprefix('service_categories') . '` (`id`) + ON DELETE SET NULL + ON UPDATE CASCADE'); + + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('services_providers') . '` + ADD CONSTRAINT `services_providers_users_provider` FOREIGN KEY (`id_users`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) + ON DELETE CASCADE + ON UPDATE CASCADE, + ADD CONSTRAINT `services_providers_services` FOREIGN KEY (`id_services`) REFERENCES `' . $this->db->dbprefix('services') . '` (`id`) + ON DELETE CASCADE + ON UPDATE CASCADE'); + + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('users') . '` + ADD CONSTRAINT `users_roles` FOREIGN KEY (`id_roles`) REFERENCES `' . $this->db->dbprefix('roles') . '` (`id`) + ON DELETE CASCADE + ON UPDATE CASCADE'); + + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('user_settings') . '` + ADD CONSTRAINT `user_settings_users` FOREIGN KEY (`id_users`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) + ON DELETE CASCADE + ON UPDATE CASCADE'); + } + + /** + * Downgrade method. + */ + public function down() + { + // Drop table constraints. + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('appointments') . '` DROP FOREIGN KEY `appointments_services`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('appointments') . '` DROP FOREIGN KEY `appointments_users_customer`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('appointments') . '` DROP FOREIGN KEY `appointments_users_provider`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('secretaries_providers') . '` DROP FOREIGN KEY `secretaries_users_secretary`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('secretaries_providers') . '` DROP FOREIGN KEY `secretaries_users_provider`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('services_providers') . '` DROP FOREIGN KEY `services_providers_users_provider`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('services_providers') . '` DROP FOREIGN KEY `services_providers_services`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('services') . '` DROP FOREIGN KEY `services_service_categories`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('users') . '` DROP FOREIGN KEY `users_roles`'); + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('user_settings') . '` DROP FOREIGN KEY `user_settings_users`'); + + // Add table constraints again. + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('appointments') . '` + ADD CONSTRAINT `' . $this->db->dbprefix('appointments') . '_ibfk_2` FOREIGN KEY (`id_users_customer`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + ADD CONSTRAINT `' . $this->db->dbprefix('appointments') . '_ibfk_3` FOREIGN KEY (`id_services`) REFERENCES `' . $this->db->dbprefix('services') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + ADD CONSTRAINT `' . $this->db->dbprefix('appointments') . '_ibfk_4` FOREIGN KEY (`id_users_provider`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE'); + + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('secretaries_providers') . '` + ADD CONSTRAINT `fk_' . $this->db->dbprefix('secretaries_providers') . '_1` FOREIGN KEY (`id_users_secretary`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + ADD CONSTRAINT `fk_' . $this->db->dbprefix('secretaries_providers') . '_2` FOREIGN KEY (`id_users_provider`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE'); + + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('services') . '` + ADD CONSTRAINT `' . $this->db->dbprefix('services') . '_ibfk_1` FOREIGN KEY (`id_service_categories`) REFERENCES `' . $this->db->dbprefix('service_categories') . '` (`id`) ON DELETE SET NULL ON UPDATE CASCADE'); + + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('services_providers') . '` + ADD CONSTRAINT `' . $this->db->dbprefix('services_providers') . '_ibfk_1` FOREIGN KEY (`id_users`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + ADD CONSTRAINT `' . $this->db->dbprefix('services_providers') . '_ibfk_2` FOREIGN KEY (`id_services`) REFERENCES `' . $this->db->dbprefix('services') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE'); + + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('users') . '` + ADD CONSTRAINT `' . $this->db->dbprefix('users') . '_ibfk_1` FOREIGN KEY (`id_roles`) REFERENCES `' . $this->db->dbprefix('roles') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE'); + + $this->db->query('ALTER TABLE `' . $this->db->dbprefix('user_settings') . '` + ADD CONSTRAINT `' . $this->db->dbprefix('user_settings') . '_ibfk_1` FOREIGN KEY (`id_users`) REFERENCES `' . $this->db->dbprefix('users') . '` (`id`) ON DELETE CASCADE ON UPDATE CASCADE'); + } +} diff --git a/application/migrations/012_legal_contents.php b/application/migrations/012_legal_contents.php new file mode 100644 index 00000000..7235e786 --- /dev/null +++ b/application/migrations/012_legal_contents.php @@ -0,0 +1,133 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.3.2 + * ---------------------------------------------------------------------------- */ + +/** + * Class Migration_Create_consents_table + * + * @property CI_DB_query_builder $db + * @property CI_DB_forge dbforge + */ +class Migration_Legal_contents extends CI_Migration { + /** + * Upgrade method. + */ + public function up() + { + $this->db->insert('settings', [ + 'name' => 'display_cookie_notice', + 'value' => '0' + ]); + + $this->db->insert('settings', [ + 'name' => 'cookie_notice_content', + 'value' => 'Cookie notice content.' + ]); + + $this->db->insert('settings', [ + 'name' => 'display_terms_and_conditions', + 'value' => '0' + ]); + + $this->db->insert('settings', [ + 'name' => 'terms_and_conditions_content', + 'value' => 'Terms and conditions content.' + ]); + + $this->db->insert('settings', [ + 'name' => 'display_privacy_policy', + 'value' => '0' + ]); + + $this->db->insert('settings', [ + 'name' => 'privacy_policy_content', + 'value' => 'Privacy policy content.' + ]); + + $this->dbforge->add_field([ + 'id' => [ + 'type' => 'INT', + 'constraint' => 11, + 'auto_increment' => TRUE + ], + 'created' => [ + 'type' => 'TIMESTAMP', + 'null' => TRUE + ], + 'modified' => [ + 'type' => 'TIMESTAMP', + 'null' => TRUE + ], + 'first_name' => [ + 'type' => 'VARCHAR', + 'constraint' => '256', + 'null' => TRUE, + ], + 'last_name' => [ + 'type' => 'VARCHAR', + 'constraint' => '256', + 'null' => TRUE, + ], + 'email' => [ + 'type' => 'VARCHAR', + 'constraint' => '512', + 'null' => TRUE, + ], + 'ip' => [ + 'type' => 'VARCHAR', + 'constraint' => '256', + 'null' => TRUE, + ], + 'type' => [ + 'type' => 'VARCHAR', + 'constraint' => '256', + 'null' => TRUE, + ], + ]); + + $this->dbforge->add_key('id', TRUE); + + $this->dbforge->create_table('consents', TRUE, ['engine' => 'InnoDB']); + } + + /** + * Downgrade method. + */ + public function down() + { + $this->db->delete('settings', [ + 'name' => 'display_cookie_notice' + ]); + + $this->db->delete('settings', [ + 'name' => 'cookie_notice_content' + ]); + + $this->db->delete('settings', [ + 'name' => 'display_terms_and_conditions' + ]); + + $this->db->delete('settings', [ + 'name' => 'terms_and_conditions_content' + ]); + + $this->db->delete('settings', [ + 'name' => 'display_privacy_policy' + ]); + + $this->db->delete('settings', [ + 'name' => 'privacy_policy_content' + ]); + + $this->dbforge->drop_table('consents'); + } +} diff --git a/application/migrations/013_add_weekday_start_setting.php b/application/migrations/013_add_weekday_start_setting.php new file mode 100644 index 00000000..df568e76 --- /dev/null +++ b/application/migrations/013_add_weekday_start_setting.php @@ -0,0 +1,39 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.3.2 + * ---------------------------------------------------------------------------- */ + +/** + * Class Migration_Add_weekday_start_setting + * + * @property CI_DB_query_builder $db + * @property CI_DB_forge dbforge + */ +class Migration_Add_weekday_start_setting extends CI_Migration { + /** + * Upgrade method. + */ + public function up() + { + $this->db->insert('settings', [ + 'name' => 'first_weekday', + 'value' => 'sunday' + ]); + } + + /** + * Downgrade method. + */ + public function down() + { + $this->db->delete('settings', ['name' => 'first_weekday']); + } +} diff --git a/application/migrations/014_create_appointment_location_column.php b/application/migrations/014_create_appointment_location_column.php new file mode 100644 index 00000000..d41119c7 --- /dev/null +++ b/application/migrations/014_create_appointment_location_column.php @@ -0,0 +1,52 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.4.0 + * ---------------------------------------------------------------------------- */ + +/** + * Class Migration_Create_appointment_location_column + * + * @property CI_DB_query_builder $db + * @property CI_DB_forge dbforge + */ +class Migration_Create_appointment_location_column extends CI_Migration { + /** + * Upgrade method. + */ + public function up() + { + $this->db->query(' + ALTER TABLE `' . $this->db->dbprefix('appointments') . '` + ADD COLUMN `location` TEXT AFTER `end_datetime`; + '); + + $this->db->query(' + ALTER TABLE `' . $this->db->dbprefix('services') . '` + ADD COLUMN `location` TEXT AFTER `description`; + '); + } + + /** + * Downgrade method. + */ + public function down() + { + $this->db->query(' + ALTER TABLE `' . $this->db->dbprefix('appointments') . '` + DROP COLUMN `location`; + '); + + $this->db->query(' + ALTER TABLE `' . $this->db->dbprefix('services') . '` + DROP COLUMN `location`; + '); + } +} diff --git a/application/migrations/015_add_working_plan_exceptions_to_user_settings.php b/application/migrations/015_add_working_plan_exceptions_to_user_settings.php new file mode 100644 index 00000000..0039ee43 --- /dev/null +++ b/application/migrations/015_add_working_plan_exceptions_to_user_settings.php @@ -0,0 +1,50 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.2.0 + * ---------------------------------------------------------------------------- */ + +/** + * Class Migration_Add_working_plan_exceptions_to_user_settings + * + * @property CI_DB_query_builder $db + * @property CI_DB_forge dbforge + */ +class Migration_Add_working_plan_exceptions_to_user_settings extends CI_Migration { + /** + * Upgrade method. + */ + public function up() + { + if ( ! $this->db->field_exists('working_plan_exceptions', 'user_settings')) + { + $fields = [ + 'working_plan_exceptions' => [ + 'type' => 'TEXT', + 'null' => TRUE, + 'after' => 'working_plan' + ] + ]; + + $this->dbforge->add_column('user_settings', $fields); + } + } + + /** + * Downgrade method. + */ + public function down() + { + if ( ! $this->db->field_exists('working_plan_exceptions', 'user_settings')) + { + $this->dbforge->drop_column('user_settings', 'working_plan_exceptions'); + } + } +} diff --git a/application/migrations/016_add_require_phone_number_setting.php b/application/migrations/016_add_require_phone_number_setting.php new file mode 100644 index 00000000..92d3676d --- /dev/null +++ b/application/migrations/016_add_require_phone_number_setting.php @@ -0,0 +1,39 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.4.0 + * ---------------------------------------------------------------------------- */ + +/** + * Class Migration_Add_require_phone_number_setting + * + * @property CI_DB_query_builder $db + * @property CI_DB_forge dbforge + */ +class Migration_Add_require_phone_number_setting extends CI_Migration { + /** + * Upgrade method. + */ + public function up() + { + $this->db->insert('settings', [ + 'name' => 'require_phone_number', + 'value' => '1' + ]); + } + + /** + * Downgrade method. + */ + public function down() + { + $this->db->delete('settings', ['name' => 'require_phone_number']); + } +} diff --git a/application/migrations/017_add_api_token_setting.php b/application/migrations/017_add_api_token_setting.php new file mode 100644 index 00000000..71a4dcf6 --- /dev/null +++ b/application/migrations/017_add_api_token_setting.php @@ -0,0 +1,43 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.4.0 + * ---------------------------------------------------------------------------- */ + +/** + * Class Migration_Add_api_token_setting + * + * @property CI_DB_query_builder $db + * @property CI_DB_forge dbforge + */ +class Migration_Add_api_token_setting extends CI_Migration { + /** + * Upgrade method. + * + * @throws Exception + */ + public function up() + { + $this->db->insert('settings', [ + 'name' => 'api_token', + 'value' => '' + ]); + } + + /** + * Downgrade method. + * + * @throws Exception + */ + public function down() + { + $this->db->delete('settings', ['name' => 'api_token']); + } +} diff --git a/application/migrations/018_add_timezone_to_users.php b/application/migrations/018_add_timezone_to_users.php new file mode 100644 index 00000000..add3aac0 --- /dev/null +++ b/application/migrations/018_add_timezone_to_users.php @@ -0,0 +1,48 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.4.0 + * ---------------------------------------------------------------------------- */ + +/** + * Class Migration_Add_timezone_to_users + * + * @property CI_DB_query_builder $db + * @property CI_DB_forge dbforge + */ +class Migration_Add_timezone_to_users extends CI_Migration { + /** + * Upgrade method. + */ + public function up() + { + if ( ! $this->db->field_exists('timezone', 'users')) + { + $fields = [ + 'timezone' => [ + 'type' => 'VARCHAR', + 'constraint' => '256', + 'default' => 'UTC', + 'after' => 'notes' + ] + ]; + + $this->dbforge->add_column('users', $fields); + } + } + + /** + * Downgrade method. + */ + public function down() + { + $this->dbforge->drop_column('users', 'timezone'); + } +} diff --git a/application/migrations/019_add_display_any_provider_setting.php b/application/migrations/019_add_display_any_provider_setting.php new file mode 100644 index 00000000..5827ce52 --- /dev/null +++ b/application/migrations/019_add_display_any_provider_setting.php @@ -0,0 +1,41 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.4.0 + * ---------------------------------------------------------------------------- */ + +/** + * Class Migration_Add_display_any_provider_setting + * + * @property CI_DB_query_builder $db + * @property CI_DB_forge dbforge + */ +class Migration_Add_display_any_provider_setting extends CI_Migration { + /** + * Upgrade method. + */ + public function up() + { + $this->db->insert('settings', [ + 'name' => 'display_any_provider', + 'value' => '1' + ]); + } + + /** + * Downgrade method. + */ + public function down() + { + $this->db->delete('settings', [ + 'name' => 'display_any_provider' + ]); + } +} diff --git a/application/migrations/020_add_language_to_users.php b/application/migrations/020_add_language_to_users.php new file mode 100644 index 00000000..329b74df --- /dev/null +++ b/application/migrations/020_add_language_to_users.php @@ -0,0 +1,48 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.4.0 + * ---------------------------------------------------------------------------- */ + +/** + * Class Migration_Add_language_to_users + * + * @property CI_DB_query_builder db + * @property CI_DB_forge dbforge + */ +class Migration_Add_language_to_users extends CI_Migration { + /** + * Upgrade method. + */ + public function up() + { + if ( ! $this->db->field_exists('language', 'users')) + { + $fields = [ + 'language' => [ + 'type' => 'VARCHAR', + 'constraint' => '256', + 'default' => 'english', + 'after' => 'timezone' + ] + ]; + + $this->dbforge->add_column('users', $fields); + } + } + + /** + * Downgrade method. + */ + public function down() + { + $this->dbforge->drop_column('users', 'language'); + } +} diff --git a/src/assets/css/index.html b/application/migrations/index.html similarity index 100% rename from src/assets/css/index.html rename to application/migrations/index.html diff --git a/application/models/Admins_model.php b/application/models/Admins_model.php new file mode 100644 index 00000000..37b5a540 --- /dev/null +++ b/application/models/Admins_model.php @@ -0,0 +1,456 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +/** + * Admins Model Class + * + * Handles the database actions for admin users management. + * + * @property CI_DB_query_builder $db + * @property CI_Loader $load + * + * @package Models + */ +class Admins_Model extends CI_Model { + /** + * Add (insert or update) an admin user record into database. + * + * @param array $admin Contains the admin user data. + * + * @return int Returns the record id. + * + * @throws Exception When the admin data are invalid (see validate() method). + */ + public function add($admin) + { + $this->validate($admin); + + if ($this->exists($admin) && ! isset($admin['id'])) + { + $admin['id'] = $this->find_record_id($admin); + } + + if ( ! isset($admin['id'])) + { + $admin['id'] = $this->insert($admin); + } + else + { + $admin['id'] = $this->update($admin); + } + + return (int)$admin['id']; + } + + /** + * Validate admin user data before add() operation is executed. + * + * @param array $admin Contains the admin user data. + * + * @return bool Returns the validation result. + * + * @throws Exception When data are invalid. + */ + public function validate($admin) + { + $this->load->helper('data_validation'); + + // If a record id is provided then check whether the record exists in the database. + if (isset($admin['id'])) + { + $num_rows = $this->db->get_where('users', ['id' => $admin['id']])->num_rows(); + + if ($num_rows === 0) + { + throw new Exception('Given admin id does not exist in database: ' . $admin['id']); + } + } + + // Validate required fields integrity. + if ( ! isset($admin['last_name']) + || ! isset($admin['email']) + || ! isset($admin['phone_number'])) + { + throw new Exception('Not all required fields are provided: ' . print_r($admin, TRUE)); + } + + // Validate admin email address. + if ( ! filter_var($admin['email'], FILTER_VALIDATE_EMAIL)) + { + throw new Exception('Invalid email address provided: ' . $admin['email']); + } + + // Check if username exists. + if (isset($admin['settings']['username'])) + { + $user_id = (isset($admin['id'])) ? $admin['id'] : ''; + if ( ! $this->validate_username($admin['settings']['username'], $user_id)) + { + throw new Exception ('Username already exists. Please select a different ' + . 'username for this record.'); + } + } + + // Validate admin password + if (isset($admin['settings']['password'])) + { + if (strlen($admin['settings']['password']) < MIN_PASSWORD_LENGTH) + { + throw new Exception('The user password must be at least ' + . MIN_PASSWORD_LENGTH . ' characters long.'); + } + } + + // Validate calendar view mode. + if (isset($admin['settings']['calendar_view']) && ($admin['settings']['calendar_view'] !== CALENDAR_VIEW_DEFAULT + && $admin['settings']['calendar_view'] !== CALENDAR_VIEW_TABLE)) + { + throw new Exception('The calendar view setting must be either "' . CALENDAR_VIEW_DEFAULT + . '" or "' . CALENDAR_VIEW_TABLE . '", given: ' . $admin['settings']['calendar_view']); + } + + // When inserting a record the email address must be unique. + $admin_id = (isset($admin['id'])) ? $admin['id'] : ''; + + $num_rows = $this->db + ->select('*') + ->from('users') + ->join('roles', 'roles.id = users.id_roles', 'inner') + ->where('roles.slug', DB_SLUG_ADMIN) + ->where('users.email', $admin['email']) + ->where('users.id <>', $admin_id) + ->get() + ->num_rows(); + + if ($num_rows > 0) + { + throw new Exception('Given email address belongs to another admin record. ' + . 'Please use a different email.'); + } + + return TRUE; // Operation completed successfully. + } + + /** + * Validate Records Username + * + * @param string $username The provider records username. + * @param int $user_id The user record id. + * + * @return bool Returns the validation result. + */ + public function validate_username($username, $user_id) + { + $num_rows = $this->db->get_where('user_settings', + ['username' => $username, 'id_users <> ' => $user_id])->num_rows(); + return ($num_rows > 0) ? FALSE : TRUE; + } + + /** + * Check whether a particular admin record exists in the database. + * + * @param array $admin Contains the admin data. The 'email' value is required to be present at the moment. + * + * @return bool Returns whether the record exists or not. + * + * @throws Exception When the 'email' value is not present on the $admin argument. + */ + public function exists($admin) + { + if ( ! isset($admin['email'])) + { + throw new Exception('Admin email is not provided: ' . print_r($admin, TRUE)); + } + + // This method shouldn't depend on another method of this class. + $num_rows = $this->db + ->select('*') + ->from('users') + ->join('roles', 'roles.id = users.id_roles', 'inner') + ->where('users.email', $admin['email']) + ->where('roles.slug', DB_SLUG_ADMIN) + ->get()->num_rows(); + + return $num_rows > 0; + } + + /** + * Find the database record id of an admin user. + * + * @param array $admin Contains the admin data. The 'email' value is required in order to find the record id. + * + * @return int Returns the record id + * + * @throws Exception When the 'email' value is not present on the $admin array. + */ + public function find_record_id($admin) + { + if ( ! isset($admin['email'])) + { + throw new Exception('Admin email was not provided: ' . print_r($admin, TRUE)); + } + + $result = $this->db + ->select('users.id') + ->from('users') + ->join('roles', 'roles.id = users.id_roles', 'inner') + ->where('users.email', $admin['email']) + ->where('roles.slug', DB_SLUG_ADMIN) + ->get(); + + if ($result->num_rows() == 0) + { + throw new Exception('Could not find admin record id.'); + } + + return (int)$result->row()->id; + } + + /** + * Insert a new admin record into the database. + * + * @param array $admin Contains the admin data. + * + * @return int Returns the new record id. + * + * @throws Exception When the insert operation fails. + */ + protected function insert($admin) + { + $this->load->helper('general'); + + $admin['id_roles'] = $this->get_admin_role_id(); + $settings = $admin['settings']; + unset($admin['settings']); + + $this->db->trans_begin(); + + if ( ! $this->db->insert('users', $admin)) + { + throw new Exception('Could not insert admin into the database.'); + } + + $admin['id'] = (int)$this->db->insert_id(); + $settings['id_users'] = $admin['id']; + $settings['salt'] = generate_salt(); + $settings['password'] = hash_password($settings['salt'], $settings['password']); + + // Insert admin settings. + if ( ! $this->db->insert('user_settings', $settings)) + { + $this->db->trans_rollback(); + throw new Exception('Could not insert admin settings into the database.'); + } + + $this->db->trans_complete(); + + return $admin['id']; + } + + /** + * Get the admin users role id. + * + * @return int Returns the role record id. + */ + public function get_admin_role_id() + { + return (int)$this->db->get_where('roles', ['slug' => DB_SLUG_ADMIN])->row()->id; + } + + /** + * Update an existing admin record in the database. + * + * @param array $admin Contains the admin record data. + * + * @return int Returns the record id. + * + * @throws Exception When the update operation fails. + */ + protected function update($admin) + { + $this->load->helper('general'); + + $settings = $admin['settings']; + unset($admin['settings']); + $settings['id_users'] = $admin['id']; + + if (isset($settings['password'])) + { + $salt = $this->db->get_where('user_settings', ['id_users' => $admin['id']])->row()->salt; + $settings['password'] = hash_password($salt, $settings['password']); + } + + $this->db->where('id', $admin['id']); + if ( ! $this->db->update('users', $admin)) + { + throw new Exception('Could not update admin record.'); + } + + $this->db->where('id_users', $settings['id_users']); + if ( ! $this->db->update('user_settings', $settings)) + { + throw new Exception('Could not update admin settings.'); + } + + return (int)$admin['id']; + } + + /** + * Delete an existing admin record from the database. + * + * @param int $admin_id The admin record id to be deleted. + * + * @return bool Returns the delete operation result. + * + * @throws Exception When the $admin_id is not a valid int value. + * @throws Exception When the record to be deleted is the only one admin user left on the system. + */ + public function delete($admin_id) + { + if ( ! is_numeric($admin_id)) + { + throw new Exception('Invalid argument type $admin_id: ' . $admin_id); + } + + // There must be always at least one admin user. If this is the only admin + // the system, it cannot be deleted. + $admin_count = $this->db->get_where('users', + ['id_roles' => $this->get_admin_role_id()])->num_rows(); + if ($admin_count == 1) + { + throw new Exception('Record could not be deleted. The system requires at least ' + . 'one admin user.'); + } + + $num_rows = $this->db->get_where('users', ['id' => $admin_id])->num_rows(); + if ($num_rows == 0) + { + return FALSE; // Record does not exist in database. + } + + return $this->db->delete('users', ['id' => $admin_id]); + } + + /** + * Get a specific admin record from the database. + * + * @param int $admin_id The id of the record to be returned. + * + * @return array Returns an array with the admin user data. + * + * @throws Exception When the $admin_id is not a valid int value. + */ + public function get_row($admin_id) + { + if ( ! is_numeric($admin_id)) + { + throw new Exception('$admin_id argument is not a valid numeric value: ' . $admin_id); + } + + // Check if record exists + if ($this->db->get_where('users', ['id' => $admin_id])->num_rows() == 0) + { + throw new Exception('The given admin id does not match a record in the database.'); + } + + $admin = $this->db->get_where('users', ['id' => $admin_id])->row_array(); + + $admin['settings'] = $this->db->get_where('user_settings', + ['id_users' => $admin_id])->row_array(); + unset($admin['settings']['id_users']); + + + return $admin; + } + + /** + * Get a specific field value from the database. + * + * @param string $field_name The field name of the value to be returned. + * @param int $admin_id Record id of the value to be returned. + * + * @return string Returns the selected record value from the database. + * + * @throws Exception When the $field_name argument is not a valid string. + * @throws Exception When the $admin_id is not a valid int. + * @throws Exception When the admin record does not exist in the database. + * @throws Exception When the selected field value is not present on database. + */ + public function get_value($field_name, $admin_id) + { + if ( ! is_string($field_name)) + { + throw new Exception('$field_name argument is not a string: ' . $field_name); + } + + if ( ! is_numeric($admin_id)) + { + throw new Exception('$admin_id argument is not a valid numeric value: ' . $admin_id); + } + + // Check whether the admin record exists. + $result = $this->db->get_where('users', ['id' => $admin_id]); + if ($result->num_rows() == 0) + { + throw new Exception('The record with the given id does not exist in the ' + . 'database: ' . $admin_id); + } + + // Check if the required field name exist in database. + $provider = $result->row_array(); + if ( ! isset($provider[$field_name])) + { + throw new Exception('The given $field_name argument does not exist in the ' + . 'database: ' . $field_name); + } + + return $provider[$field_name]; + } + + /** + * Get all, or specific admin records from database. + * + * @param mixed|null $where (OPTIONAL) The WHERE clause of the query to be executed. Use this to get + * specific admin records. + * @param mixed|null $order_by + * @param int|null $limit + * @param int|null $offset + * @return array Returns an array with admin records. + */ + public function get_batch($where = NULL, $order_by = NULL, $limit = NULL, $offset = NULL) + { + $role_id = $this->get_admin_role_id(); + + if ($where !== NULL) + { + $this->db->where($where); + } + + if ($order_by !== NULL) + { + $this->db->order_by($order_by); + } + + $batch = $this->db->get_where('users', ['id_roles' => $role_id], $limit, $offset)->result_array(); + + // Get every admin settings. + foreach ($batch as &$admin) + { + $admin['settings'] = $this->db->get_where('user_settings', + ['id_users' => $admin['id']])->row_array(); + unset($admin['settings']['id_users']); + } + + return $batch; + } +} diff --git a/application/models/Appointments_model.php b/application/models/Appointments_model.php new file mode 100644 index 00000000..5f86f8c5 --- /dev/null +++ b/application/models/Appointments_model.php @@ -0,0 +1,570 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +/** + * Appointments Model + * + * @property CI_DB_query_builder $db + * @property CI_Loader $load + * + * @package Models + */ +class Appointments_Model extends CI_Model { + /** + * Add an appointment record to the database. + * + * This method adds a new appointment to the database. If the appointment doesn't exists it is going to be inserted, + * otherwise the record is going to be updated. + * + * @param array $appointment Associative array with the appointment data. Each key has the same name with the + * database fields. + * + * @return int Returns the appointments id. + * @throws Exception + */ + public function add($appointment) + { + // Validate the appointment data before doing anything. + $this->validate($appointment); + + // Perform insert() or update() operation. + if ( ! isset($appointment['id'])) + { + $appointment['id'] = $this->insert($appointment); + } + else + { + $this->update($appointment); + } + + return $appointment['id']; + } + + /** + * Validate appointment data before the insert or update operations are executed. + * + * @param array $appointment Contains the appointment data. + * + * @return bool Returns the validation result. + * + * @throws Exception If appointment validation fails. + */ + public function validate($appointment) + { + $this->load->helper('data_validation'); + + // If a appointment id is given, check whether the record exists in the database. + if (isset($appointment['id'])) + { + $num_rows = $this->db->get_where('appointments', ['id' => $appointment['id']])->num_rows(); + + if ($num_rows === 0) + { + throw new Exception('Provided appointment id does not exist in the database.'); + } + } + + // Check if appointment dates are valid. + if ( ! validate_mysql_datetime($appointment['start_datetime'])) + { + throw new Exception('Appointment start datetime is invalid.'); + } + + if ( ! validate_mysql_datetime($appointment['end_datetime'])) + { + throw new Exception('Appointment end datetime is invalid.'); + } + + // Ensure the appointment lasts longer than the minimum duration (in minutes). + $diff = (strtotime($appointment['end_datetime']) - strtotime($appointment['start_datetime'])) / 60; + + if ($diff < EVENT_MINIMUM_DURATION) + { + throw new Exception('The appointment duration is less than the minimum duration (' + . EVENT_MINIMUM_DURATION . ' minutes).'); + } + + // Check if the provider's id is valid. + $num_rows = $this->db + ->select('*') + ->from('users') + ->join('roles', 'roles.id = users.id_roles', 'inner') + ->where('users.id', $appointment['id_users_provider']) + ->where('roles.slug', DB_SLUG_PROVIDER) + ->get()->num_rows(); + if ($num_rows == 0) + { + throw new Exception('Appointment provider id is invalid.'); + } + + if ($appointment['is_unavailable'] == FALSE) + { + // Check if the customer's id is valid. + $num_rows = $this->db + ->select('*') + ->from('users') + ->join('roles', 'roles.id = users.id_roles', 'inner') + ->where('users.id', $appointment['id_users_customer']) + ->where('roles.slug', DB_SLUG_CUSTOMER) + ->get()->num_rows(); + if ($num_rows == 0) + { + throw new Exception('Appointment customer id is invalid.'); + } + + // Check if the service id is valid. + $num_rows = $this->db->get_where('services', + ['id' => $appointment['id_services']])->num_rows(); + if ($num_rows == 0) + { + throw new Exception('Appointment service id is invalid.'); + } + } + + return TRUE; + } + + /** + * Insert a new appointment record to the database. + * + * @param array $appointment Associative array with the appointment's data. Each key has the same name with the + * database fields. + * + * @return int Returns the id of the new record. + * + * @throws Exception If appointment record could not be inserted. + */ + protected function insert($appointment) + { + $appointment['book_datetime'] = date('Y-m-d H:i:s'); + $appointment['hash'] = $this->generate_hash(); + + if ( ! $this->db->insert('appointments', $appointment)) + { + throw new Exception('Could not insert appointment record.'); + } + + return (int)$this->db->insert_id(); + } + + /** + * Generate a unique hash for the given appointment data. + * + * This method uses the current date-time to generate a unique hash string that is later used to identify this + * appointment. Hash is needed when the email is send to the user with an edit link. + * + * @return string Returns the unique appointment hash. + */ + public function generate_hash() + { + $current_date = new DateTime(); + return md5($current_date->getTimestamp()); + } + + /** + * Update an existing appointment record in the database. + * + * The appointment data argument should already include the record ID in order to process the update operation. + * + * @param array $appointment Associative array with the appointment's data. Each key has the same name with the + * database fields. + * + * @throws Exception If appointment record could not be updated. + */ + protected function update($appointment) + { + $this->db->where('id', $appointment['id']); + if ( ! $this->db->update('appointments', $appointment)) + { + throw new Exception('Could not update appointment record.'); + } + } + + /** + * Check if a particular appointment record already exists. + * + * This method checks whether the given appointment already exists in the database. It doesn't search with the id, + * but by using the following fields: "start_datetime", "end_datetime", "id_users_provider", "id_users_customer", + * "id_services". + * + * @param array $appointment Associative array with the appointment's data. Each key has the same name with the + * database fields. + * + * @return bool Returns whether the record exists or not. + * + * @throws Exception If appointment fields are missing. + */ + public function exists($appointment) + { + if ( ! isset($appointment['start_datetime']) + || ! isset($appointment['end_datetime']) + || ! isset($appointment['id_users_provider']) + || ! isset($appointment['id_users_customer']) + || ! isset($appointment['id_services'])) + { + throw new Exception('Not all appointment field values are provided: ' + . print_r($appointment, TRUE)); + } + + $num_rows = $this->db->get_where('appointments', [ + 'start_datetime' => $appointment['start_datetime'], + 'end_datetime' => $appointment['end_datetime'], + 'id_users_provider' => $appointment['id_users_provider'], + 'id_users_customer' => $appointment['id_users_customer'], + 'id_services' => $appointment['id_services'], + ]) + ->num_rows(); + + return ($num_rows > 0) ? TRUE : FALSE; + } + + /** + * Find the database id of an appointment record. + * + * The appointment data should include the following fields in order to get the unique id from the database: + * "start_datetime", "end_datetime", "id_users_provider", "id_users_customer", "id_services". + * + * IMPORTANT: The record must already exists in the database, otherwise an exception is raised. + * + * @param array $appointment Array with the appointment data. The keys of the array should have the same names as + * the db fields. + * + * @return int Returns the db id of the record that matches the appointment data. + * + * @throws Exception If appointment could not be found. + */ + public function find_record_id($appointment) + { + $this->db->where([ + 'start_datetime' => $appointment['start_datetime'], + 'end_datetime' => $appointment['end_datetime'], + 'id_users_provider' => $appointment['id_users_provider'], + 'id_users_customer' => $appointment['id_users_customer'], + 'id_services' => $appointment['id_services'] + ]); + + $result = $this->db->get('appointments'); + + if ($result->num_rows() == 0) + { + throw new Exception('Could not find appointment record id.'); + } + + return $result->row()->id; + } + + /** + * Delete an existing appointment record from the database. + * + * @param int $appointment_id The record id to be deleted. + * + * @return bool Returns the delete operation result. + * + * @throws Exception If $appointment_id argument is invalid. + */ + public function delete($appointment_id) + { + if ( ! is_numeric($appointment_id)) + { + throw new Exception('Invalid argument type $appointment_id (value:"' . $appointment_id . '")'); + } + + $num_rows = $this->db->get_where('appointments', ['id' => $appointment_id])->num_rows(); + + if ($num_rows == 0) + { + return FALSE; // Record does not exist. + } + + $this->db->where('id', $appointment_id); + return $this->db->delete('appointments'); + } + + /** + * Get a specific row from the appointments table. + * + * @param int $appointment_id The record's id to be returned. + * + * @return array Returns an associative array with the selected record's data. Each key has the same name as the + * database field names. + * + * @throws Exception If $appointment_id argumnet is invalid. + */ + public function get_row($appointment_id) + { + if ( ! is_numeric($appointment_id)) + { + throw new Exception('Invalid argument given. Expected integer for the $appointment_id: ' + . $appointment_id); + } + + $appointment = $this->db->get_where('appointments', ['id' => $appointment_id])->row_array(); + + $this->load->library('timezones'); + + $appointment = $this->timezones->convert_event_timezone($appointment); + + return $appointment; + } + + /** + * Get a specific field value from the database. + * + * @param string $field_name The field name of the value to be returned. + * @param int $appointment_id The selected record's id. + * + * @return string Returns the records value from the database. + * + * @throws Exception If $appointment_id argument is invalid. + * @throws Exception If $field_name argument is invalid. + * @throws Exception If requested appointment record was not found. + * @throws Exception If requested field name does not exist. + */ + public function get_value($field_name, $appointment_id) + { + if ( ! is_numeric($appointment_id)) + { + throw new Exception('Invalid argument given, expected integer for the $appointment_id: ' + . $appointment_id); + } + + if ( ! is_string($field_name)) + { + throw new Exception('Invalid argument given, expected string for the $field_name: ' . $field_name); + } + + if ($this->db->get_where('appointments', ['id' => $appointment_id])->num_rows() == 0) + { + throw new Exception('The record with the provided id ' + . 'does not exist in the database: ' . $appointment_id); + } + + $row_data = $this->db->get_where('appointments', ['id' => $appointment_id])->row_array(); + + if ( ! isset($row_data[$field_name])) + { + throw new Exception('The given field name does not exist in the database: ' . $field_name); + } + + $this->load->library('timezones'); + + $row_data = $this->timezones->convert_event_timezone($row_data); + + return $row_data[$field_name]; + } + + /** + * Get all, or specific records from appointment's table. + * + * Example: + * + * $this->Model->getBatch('id = ' . $recordId); + * + * @param mixed|null $where (OPTIONAL) The WHERE clause of the query to be executed. DO NOT INCLUDE 'WHERE' + * KEYWORD. + * @param mixed|null $order_by + * @param int|null $limit + * @param int|null $offset + * @param bool $aggregates (OPTIONAL) Defines whether to add aggregations or not. + * + * @return array Returns the rows from the database. + */ + public function get_batch($where = NULL, $order_by = NULL, $limit = NULL, $offset = NULL, $aggregates = FALSE) + { + if ($where !== NULL) + { + $this->db->where($where); + } + + if ($order_by) + { + $this->db->order_by($order_by); + } + + $appointments = $this->db->get('appointments', $limit, $offset)->result_array(); + + $this->load->library('timezones'); + + foreach ($appointments as &$appointment) + { + $appointment = $this->timezones->convert_event_timezone($appointment); + + if ($aggregates) + { + $appointment = $this->get_aggregates($appointment); + } + } + + return $appointments; + } + + /** + * Get the aggregates of an appointment. + * + * @param array $appointment Appointment data. + * + * @return array Returns the appointment with the aggregates. + */ + private function get_aggregates(array $appointment) + { + $appointment['service'] = $this->db->get_where('services', + ['id' => $appointment['id_services']])->row_array(); + $appointment['provider'] = $this->db->get_where('users', + ['id' => $appointment['id_users_provider']])->row_array(); + $appointment['customer'] = $this->db->get_where('users', + ['id' => $appointment['id_users_customer']])->row_array(); + return $appointment; + } + + /** + * Inserts or updates an unavailable period record in the database. + * + * @param array $unavailable Contains the unavailable data. + * + * @return int Returns the record id. + * + * @throws Exception If unavailability validation fails. + * @throws Exception If provider record could not be found in database. + */ + public function add_unavailable($unavailable) + { + // Validate period + $start = strtotime($unavailable['start_datetime']); + $end = strtotime($unavailable['end_datetime']); + if ($start > $end) + { + throw new Exception('Unavailable period start must be prior to end.'); + } + + // Validate provider record + $where_clause = [ + 'id' => $unavailable['id_users_provider'], + 'id_roles' => $this->db->get_where('roles', ['slug' => DB_SLUG_PROVIDER])->row()->id + ]; + + if ($this->db->get_where('users', $where_clause)->num_rows() == 0) + { + throw new Exception('Provider id was not found in database.'); + } + + // Add record to database (insert or update). + if ( ! isset($unavailable['id'])) + { + $unavailable['book_datetime'] = date('Y-m-d H:i:s'); + $unavailable['is_unavailable'] = TRUE; + + $this->db->insert('appointments', $unavailable); + $unavailable['id'] = $this->db->insert_id(); + } + else + { + $this->db->where(['id' => $unavailable['id']]); + $this->db->update('appointments', $unavailable); + } + + return $unavailable['id']; + } + + /** + * Delete an unavailable period. + * + * @param int $unavailable_id Record id to be deleted. + * + * @return bool Returns the delete operation result. + * + * @throws Exception If $unavailable_id argument is invalid. + */ + public function delete_unavailable($unavailable_id) + { + if ( ! is_numeric($unavailable_id)) + { + throw new Exception('Invalid argument type $unavailable_id: ' . $unavailable_id); + } + + $num_rows = $this->db->get_where('appointments', ['id' => $unavailable_id])->num_rows(); + + if ($num_rows == 0) + { + return FALSE; // Record does not exist. + } + + $this->db->where('id', $unavailable_id); + + return $this->db->delete('appointments'); + } + + /** + * Clear google sync IDs from appointment record. + * + * @param int $provider_id The appointment provider record id. + * + * @throws Exception If $provider_id argument is invalid. + */ + public function clear_google_sync_ids($provider_id) + { + if ( ! is_numeric($provider_id)) + { + throw new Exception('Invalid argument type $provider_id: ' . $provider_id); + } + + $this->db->update('appointments', ['id_google_calendar' => NULL], + ['id_users_provider' => $provider_id]); + } + + /** + * Get appointment count for the provided start datetime. + * + * @param int $service_id Selected service ID. + * @param string $selected_date Selected date string. + * @param string $hour Selected hour string. + * + * @return int Returns the appointment number at the selected start time. + */ + public function appointment_count_for_hour($service_id, $selected_date, $hour) + { + return $this->db->get_where('appointments', [ + 'id_services' => $service_id, + 'start_datetime' => date('Y-m-d H:i:s', strtotime($selected_date . ' ' . $hour . ':00')) + ])->num_rows(); + } + + /** + * Returns the attendants number for selection period. + * + * @param DateTime $slot_start When the slot starts + * @param DateTime $slot_end When the slot ends. + * @param int $service_id Selected service ID. + * + * @return int Returns the number of attendants for selected time period. + */ + public function get_attendants_number_for_period(DateTime $slot_start, DateTime $slot_end, $service_id) + { + return (int)$this->db + ->select('count(*) AS attendants_number') + ->from('appointments') + ->group_start() + ->group_start() + ->where('start_datetime <=', $slot_start->format('Y-m-d H:i:s')) + ->where('end_datetime >', $slot_start->format('Y-m-d H:i:s')) + ->group_end() + ->or_group_start() + ->where('start_datetime <', $slot_end->format('Y-m-d H:i:s')) + ->where('end_datetime >=', $slot_end->format('Y-m-d H:i:s')) + ->group_end() + ->group_end() + ->where('id_services', $service_id) + ->get() + ->row() + ->attendants_number; + } +} diff --git a/application/models/Consents_model.php b/application/models/Consents_model.php new file mode 100644 index 00000000..49d0e524 --- /dev/null +++ b/application/models/Consents_model.php @@ -0,0 +1,115 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.3.2 + * ---------------------------------------------------------------------------- */ + +/** + * Class Consents_model + * + * @property CI_DB_query_builder $db + * @property CI_Loader $load + * + * @package Models + */ +class Consents_model extends CI_Model { + /** + * Add a consent record to the database. + * + * This method adds a consent to the database. + * + * @param array $consent Associative array with the consent's data. + * + * @return int Returns the consent ID. + * + * @throws Exception + */ + public function add($consent) + { + $this->validate($consent); + + if ( ! isset($consent['id'])) + { + $consent['id'] = $this->insert($consent); + } + else + { + $this->update($consent); + } + + return $consent['id']; + } + + + /** + * Validate consent data before the insert or update operation is executed. + * + * @param array $consent Contains the consent data. + * + * @throws Exception If customer validation fails. + */ + public function validate($consent) + { + if ( ! isset($consent['first_name']) + || ! isset($consent['last_name']) + || ! isset($consent['email']) + || ! isset($consent['ip']) + || ! isset($consent['type'])) + { + throw new Exception('Not all required fields are provided: ' + . print_r($consent, TRUE)); + } + } + + /** + * Insert a new consent record to the database. + * + * @param array $consent Associative array with the consent's data. + * + * @return int Returns the ID of the new record. + * + * @throws Exception If consent record could not be inserted. + */ + protected function insert($consent) + { + $consent['created'] = date('Y-m-d H:i:s'); + $consent['modified'] = date('Y-m-d H:i:s'); + + if ( ! $this->db->insert('consents', $consent)) + { + throw new Exception('Could not insert consent to the database.'); + } + + return (int)$this->db->insert_id(); + } + + /** + * Update an existing consent record in the database. + * + * The consent data argument should already include the record ID in order to process the update operation. + * + * @param array $consent Associative array with the consent's data. + * + * @return int Returns the updated record ID. + * + * @throws Exception If consent record could not be updated. + */ + protected function update($consent) + { + $consent['modified'] = date('Y-m-d H:i:s'); + + if ( ! $this->db->update('consents', $consent, ['id' => $consent['id']])) + { + throw new Exception('Could not update consent to the database.'); + } + + return (int)$consent['id']; + } +} diff --git a/application/models/Customers_model.php b/application/models/Customers_model.php new file mode 100644 index 00000000..d11fa165 --- /dev/null +++ b/application/models/Customers_model.php @@ -0,0 +1,382 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +/** + * Customers Model + * + * @property CI_DB_query_builder $db + * @property CI_Loader $load + * + * @package Models + */ +class Customers_Model extends CI_Model { + /** + * Add a customer record to the database. + * + * This method adds a customer to the database. If the customer doesn't exists it is going to be inserted, otherwise + * the record is going to be updated. + * + * @param array $customer Associative array with the customer's data. Each key has the same name with the database + * fields. + * + * @return int Returns the customer id. + * @throws Exception + */ + public function add($customer) + { + // Validate the customer data before doing anything. + $this->validate($customer); + + // :: CHECK IF CUSTOMER ALREADY EXIST (FROM EMAIL). + if ($this->exists($customer) && ! isset($customer['id'])) + { + // Find the customer id from the database. + $customer['id'] = $this->find_record_id($customer); + } + + // :: INSERT OR UPDATE CUSTOMER RECORD + if ( ! isset($customer['id'])) + { + $customer['id'] = $this->insert($customer); + } + else + { + $this->update($customer); + } + + return $customer['id']; + } + + /** + * Validate customer data before the insert or update operation is executed. + * + * @param array $customer Contains the customer data. + * + * @return bool Returns the validation result. + * + * @throws Exception If customer validation fails. + */ + public function validate($customer) + { + $this->load->helper('data_validation'); + + // If a customer id is provided, check whether the record + // exist in the database. + if (isset($customer['id'])) + { + $num_rows = $this->db->get_where('users', + ['id' => $customer['id']])->num_rows(); + if ($num_rows == 0) + { + throw new Exception('Provided customer id does not ' + . 'exist in the database.'); + } + } + + $query = $this->db->get_where('settings', ['name' => 'require_phone_number']); + $phone_number_required = $query->num_rows() > 0 ? $query->row() === '1' : FALSE; + + // Validate required fields + if (empty($customer['first_name']) + || empty($customer['last_name']) + || empty($customer['email']) + || (empty($customer['phone_number']) && $phone_number_required)) + { + throw new Exception('Not all required fields are provided: ' + . print_r($customer, TRUE)); + } + + // Validate email address + if ( ! filter_var($customer['email'], FILTER_VALIDATE_EMAIL)) + { + throw new Exception('Invalid email address provided: ' + . $customer['email']); + } + + // When inserting a record the email address must be unique. + $customer_id = (isset($customer['id'])) ? $customer['id'] : ''; + + $num_rows = $this->db + ->select('*') + ->from('users') + ->join('roles', 'roles.id = users.id_roles', 'inner') + ->where('roles.slug', DB_SLUG_CUSTOMER) + ->where('users.email', $customer['email']) + ->where('users.id <>', $customer_id) + ->get() + ->num_rows(); + + if ($num_rows > 0) + { + throw new Exception('Given email address belongs to another customer record. ' + . 'Please use a different email.'); + } + + return TRUE; + } + + /** + * Check if a particular customer record already exists. + * + * This method checks whether the given customer already exists in the database. It doesn't search with the id, but + * with the following fields: "email" + * + * @param array $customer Associative array with the customer's data. Each key has the same name with the database + * fields. + * + * @return bool Returns whether the record exists or not. + * + * @throws Exception If customer email property is missing. + */ + public function exists($customer) + { + if (empty($customer['email'])) + { + throw new Exception('Customer\'s email is not provided.'); + } + + // This method shouldn't depend on another method of this class. + $num_rows = $this->db + ->select('*') + ->from('users') + ->join('roles', 'roles.id = users.id_roles', 'inner') + ->where('users.email', $customer['email']) + ->where('roles.slug', DB_SLUG_CUSTOMER) + ->get()->num_rows(); + + return ($num_rows > 0) ? TRUE : FALSE; + } + + /** + * Find the database id of a customer record. + * + * The customer data should include the following fields in order to get the unique id from the database: "email" + * + * IMPORTANT: The record must already exists in the database, otherwise an exception is raised. + * + * @param array $customer Array with the customer data. The keys of the array should have the same names as the + * database fields. + * + * @return int Returns the ID. + * + * @throws Exception If customer record does not exist. + */ + public function find_record_id($customer) + { + if (empty($customer['email'])) + { + throw new Exception('Customer\'s email was not provided: ' + . print_r($customer, TRUE)); + } + + // Get customer's role id + $result = $this->db + ->select('users.id') + ->from('users') + ->join('roles', 'roles.id = users.id_roles', 'inner') + ->where('users.email', $customer['email']) + ->where('roles.slug', DB_SLUG_CUSTOMER) + ->get(); + + if ($result->num_rows() == 0) + { + throw new Exception('Could not find customer record id.'); + } + + return $result->row()->id; + } + + /** + * Insert a new customer record to the database. + * + * @param array $customer Associative array with the customer's data. Each key has the same name with the database + * fields. + * + * @return int Returns the id of the new record. + * + * @throws Exception If customer record could not be inserted. + */ + protected function insert($customer) + { + // Before inserting the customer we need to get the customer's role id + // from the database and assign it to the new record as a foreign key. + $customer_role_id = $this->db + ->select('id') + ->from('roles') + ->where('slug', DB_SLUG_CUSTOMER) + ->get()->row()->id; + + $customer['id_roles'] = $customer_role_id; + + if ( ! $this->db->insert('users', $customer)) + { + throw new Exception('Could not insert customer to the database.'); + } + + return (int)$this->db->insert_id(); + } + + /** + * Update an existing customer record in the database. + * + * The customer data argument should already include the record ID in order to process the update operation. + * + * @param array $customer Associative array with the customer's data. Each key has the same name with the database + * fields. + * + * @return int Returns the updated record ID. + * + * @throws Exception If customer record could not be updated. + */ + protected function update($customer) + { + $this->db->where('id', $customer['id']); + + if ( ! $this->db->update('users', $customer)) + { + throw new Exception('Could not update customer to the database.'); + } + + return (int)$customer['id']; + } + + /** + * Delete an existing customer record from the database. + * + * @param int $customer_id The record id to be deleted. + * + * @return bool Returns the delete operation result. + * + * @throws Exception If $customer_id argument is invalid. + */ + public function delete($customer_id) + { + if ( ! is_numeric($customer_id)) + { + throw new Exception('Invalid argument type $customer_id: ' . $customer_id); + } + + $num_rows = $this->db->get_where('users', ['id' => $customer_id])->num_rows(); + if ($num_rows == 0) + { + return FALSE; + } + + return $this->db->delete('users', ['id' => $customer_id]); + } + + /** + * Get a specific row from the appointments table. + * + * @param int $customer_id The record's id to be returned. + * + * @return array Returns an associative array with the selected record's data. Each key has the same name as the + * database field names. + * + * @throws Exception If $customer_id argumnet is invalid. + */ + public function get_row($customer_id) + { + if ( ! is_numeric($customer_id)) + { + throw new Exception('Invalid argument provided as $customer_id : ' . $customer_id); + } + return $this->db->get_where('users', ['id' => $customer_id])->row_array(); + } + + /** + * Get a specific field value from the database. + * + * @param string $field_name The field name of the value to be returned. + * @param int $customer_id The selected record's id. + * + * @return string Returns the records value from the database. + * + * @throws Exception If $customer_id argument is invalid. + * @throws Exception If $field_name argument is invalid. + * @throws Exception If requested customer record does not exist in the database. + * @throws Exception If requested field name does not exist in the database. + */ + public function get_value($field_name, $customer_id) + { + if ( ! is_numeric($customer_id)) + { + throw new Exception('Invalid argument provided as $customer_id: ' + . $customer_id); + } + + if ( ! is_string($field_name)) + { + throw new Exception('$field_name argument is not a string: ' + . $field_name); + } + + if ($this->db->get_where('users', ['id' => $customer_id])->num_rows() == 0) + { + throw new Exception('The record with the $customer_id argument ' + . 'does not exist in the database: ' . $customer_id); + } + + $row_data = $this->db->get_where('users', ['id' => $customer_id] + )->row_array(); + if ( ! isset($row_data[$field_name])) + { + throw new Exception('The given $field_name argument does not' + . 'exist in the database: ' . $field_name); + } + + $customer = $this->db->get_where('users', ['id' => $customer_id])->row_array(); + + return $customer[$field_name]; + } + + /** + * Get all, or specific records from appointment's table. + * + * Example: + * + * $this->Model->getBatch('id = ' . $recordId); + * + * @param mixed|null $where + * @param midex|null $order_by + * @param int|null $limit + * @param int|null $offset + * @return array Returns the rows from the database. + */ + public function get_batch($where = NULL, $order_by = NULL, $limit = NULL, $offset = NULL) + { + $role_id = $this->get_customers_role_id(); + + if ($where !== NULL) + { + $this->db->where($where); + } + + if ($order_by !== NULL) + { + $this->db->order_by($order_by); + } + + return $this->db->get_where('users', ['id_roles' => $role_id], $limit, $offset)->result_array(); + } + + /** + * Get the customers role id from the database. + * + * @return int Returns the role id for the customer records. + */ + public function get_customers_role_id() + { + return $this->db->get_where('roles', ['slug' => DB_SLUG_CUSTOMER])->row()->id; + } +} diff --git a/application/models/Providers_model.php b/application/models/Providers_model.php new file mode 100755 index 00000000..cf354cd8 --- /dev/null +++ b/application/models/Providers_model.php @@ -0,0 +1,730 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +/** + * Providers_Model Class + * + * Contains the database operations for the service provider users of Easy!Appointments. + * + * @property CI_DB_query_builder $db + * @property CI_Loader $load + * + * @package Models + */ +class Providers_Model extends CI_Model { + /** + * Add (insert - update) a service provider record. + * + * If the record already exists (id value provided) then it is going to be updated, otherwise inserted into the + * database. + * + * @param array $provider Contains the service provider data. + * + * @return int Returns the record id. + * + * @throws Exception When the record data validation fails. + */ + public function add($provider) + { + $this->validate($provider); + + if ($this->exists($provider) && ! isset($provider['id'])) + { + $provider['id'] = $this->find_record_id($provider); + } + + if ( ! isset($provider['id'])) + { + $provider['id'] = $this->insert($provider); + } + else + { + $provider['id'] = $this->update($provider); + } + + return (int)$provider['id']; + } + + /** + * Validate provider data before the insert or update operation is executed. + * + * @param array $provider Contains the provider data. + * + * @return bool Returns the validation result. + * + * @throws Exception If provider validation fails. + */ + public function validate($provider) + { + $this->load->helper('data_validation'); + + // If a provider id is present, check whether the record exist in the database. + if (isset($provider['id'])) + { + $num_rows = $this->db->get_where('users', + ['id' => $provider['id']])->num_rows(); + if ($num_rows == 0) + { + throw new Exception('Provided record id does not exist in the database.'); + } + } + + // Validate required fields. + if ( ! isset($provider['last_name']) + || ! isset($provider['email']) + || ! isset($provider['phone_number'])) + { + throw new Exception('Not all required fields are provided: ' . print_r($provider, TRUE)); + } + + // Validate provider email address. + if ( ! filter_var($provider['email'], FILTER_VALIDATE_EMAIL)) + { + throw new Exception('Invalid email address provided: ' . $provider['email']); + } + + // Validate provider services. + if ( ! isset($provider['services']) || ! is_array($provider['services'])) + { + throw new Exception('Invalid provider services given: ' . print_r($provider, TRUE)); + } + else + { // Check if services are valid int values. + foreach ($provider['services'] as $service_id) + { + if ( ! is_numeric($service_id)) + { + throw new Exception('A provider service with invalid id was found: ' + . print_r($provider, TRUE)); + } + } + } + + // Validate provider settings. + if ( ! isset($provider['settings']) || count($provider['settings']) == 0 + || ! is_array($provider['settings'])) + { + throw new Exception('Invalid provider settings given: ' . print_r($provider, TRUE)); + } + + // Check if username exists. + if (isset($provider['settings']['username'])) + { + $user_id = (isset($provider['id'])) ? $provider['id'] : ''; + if ( ! $this->validate_username($provider['settings']['username'], $user_id)) + { + throw new Exception ('Username already exists. Please select a different ' + . 'username for this record.'); + } + } + + // Validate provider password + if (isset($provider['settings']['password'])) + { + if (strlen($provider['settings']['password']) < MIN_PASSWORD_LENGTH) + { + throw new Exception('The user password must be at least ' + . MIN_PASSWORD_LENGTH . ' characters long.'); + } + } + + // Validate calendar view mode. + if (isset($provider['settings']['calendar_view']) && ($provider['settings']['calendar_view'] !== CALENDAR_VIEW_DEFAULT + && $provider['settings']['calendar_view'] !== CALENDAR_VIEW_TABLE)) + { + throw new Exception('The calendar view setting must be either "' . CALENDAR_VIEW_DEFAULT + . '" or "' . CALENDAR_VIEW_TABLE . '", given: ' . $provider['settings']['calendar_view']); + } + + // When inserting a record the email address must be unique. + $provider_id = (isset($provider['id'])) ? $provider['id'] : ''; + + $num_rows = $this->db + ->select('*') + ->from('users') + ->join('roles', 'roles.id = users.id_roles', 'inner') + ->where('roles.slug', DB_SLUG_PROVIDER) + ->where('users.email', $provider['email']) + ->where('users.id <>', $provider_id) + ->get() + ->num_rows(); + + if ($num_rows > 0) + { + throw new Exception('Given email address belongs to another provider record. ' + . 'Please use a different email.'); + } + + return TRUE; + } + + /** + * Validate Records Username + * + * @param string $username The provider records username. + * @param int $user_id The user record id. + * + * @return bool Returns the validation result. + */ + public function validate_username($username, $user_id) + { + $num_rows = $this->db->get_where('user_settings', + ['username' => $username, 'id_users <> ' => $user_id])->num_rows(); + return ($num_rows > 0) ? FALSE : TRUE; + } + + /** + * Check whether a particular provider record already exists in the database. + * + * @param array $provider Contains the provider data. The 'email' value is required in order to check for a provider. + * + * @return bool Returns whether the provider record exists or not. + * + * @throws Exception When the 'email' value is not provided. + */ + public function exists($provider) + { + if ( ! isset($provider['email'])) + { + throw new Exception('Provider email is not provided:' . print_r($provider, TRUE)); + } + + // This method shouldn't depend on another method of this class. + $num_rows = $this->db + ->select('*') + ->from('users') + ->join('roles', 'roles.id = users.id_roles', 'inner') + ->where('users.email', $provider['email']) + ->where('roles.slug', DB_SLUG_PROVIDER) + ->get()->num_rows(); + + return ($num_rows > 0) ? TRUE : FALSE; + } + + /** + * Find the database record id of a provider. + * + * @param array $provider Contains the provider data. The 'email' value is required in order to find the record id. + * + * @return int Returns the record id. + * + * @throws Exception When the provider's email value is not provided. + */ + public function find_record_id($provider) + { + if ( ! isset($provider['email'])) + { + throw new Exception('Provider email was not provided:' . print_r($provider, TRUE)); + } + + $result = $this->db + ->select('users.id') + ->from('users') + ->join('roles', 'roles.id = users.id_roles', 'inner') + ->where('users.email', $provider['email']) + ->where('roles.slug', DB_SLUG_PROVIDER) + ->get(); + + if ($result->num_rows() == 0) + { + throw new Exception('Could not find provider record id.'); + } + + return (int)$result->row()->id; + } + + /** + * Insert a new provider record into the database. + * + * @param array $provider Contains the provider data (must be already validated). + * + * @return int Returns the new record id. + * + * @throws Exception When the insert operation fails. + */ + protected function insert($provider) + { + $this->load->helper('general'); + + // Get provider role id. + $provider['id_roles'] = $this->get_providers_role_id(); + + // Store provider settings and services (must not be present on the $provider array). + $services = $provider['services']; + unset($provider['services']); + $settings = $provider['settings']; + unset($provider['settings']); + + // Insert provider record and save settings. + if ( ! $this->db->insert('users', $provider)) + { + throw new Exception('Could not insert provider into the database'); + } + + $settings['salt'] = generate_salt(); + $settings['password'] = hash_password($settings['salt'], $settings['password']); + + $provider['id'] = $this->db->insert_id(); + $this->save_settings($settings, $provider['id']); + $this->save_services($services, $provider['id']); + + // Return the new record id. + return (int)$provider['id']; + } + + /** + * Get the providers role id from the database. + * + * @return int Returns the role id for the provider records. + */ + public function get_providers_role_id() + { + return $this->db->get_where('roles', ['slug' => DB_SLUG_PROVIDER])->row()->id; + } + + /** + * Save the provider settings (used from insert or update operation). + * + * @param array $settings Contains the setting values. + * @param int $provider_id Record id of the provider. + * + * @throws Exception If $provider_id argument is invalid. + * @throws Exception If $settings argument is invalid. + */ + protected function save_settings($settings, $provider_id) + { + if ( ! is_numeric($provider_id)) + { + throw new Exception('Invalid $provider_id argument given:' . $provider_id); + } + + if (count($settings) == 0 || ! is_array($settings)) + { + throw new Exception('Invalid $settings argument given:' . print_r($settings, TRUE)); + } + + // Check if the setting record exists in db. + if ($this->db->get_where('user_settings', ['id_users' => $provider_id])->num_rows() === 0) + { + $this->db->insert('user_settings', ['id_users' => $provider_id]); + } + + foreach ($settings as $name => $value) + { + // Sort in descending order the working plan exceptions in a reverse order (makes it easier to edit them + // later on). + if ($name === 'working_plan_exceptions') + { + $value = json_decode($value, TRUE); + krsort($value); + $value = json_encode($value); + } + + $this->set_setting($name, $value, $provider_id); + } + } + + /** + * Set a provider's setting value in the database. + * + * The provider and settings record must already exist. + * + * @param string $setting_name The setting's name. + * @param string $value The setting's value. + * @param int $provider_id The selected provider id. + */ + public function set_setting($setting_name, $value, $provider_id) + { + $this->db->where(['id_users' => $provider_id]); + return $this->db->update('user_settings', [$setting_name => $value]); + } + + /** + * Save the provider services in the database (use on both insert and update operation). + * + * @param array $services Contains the service ids that the selected provider can provide. + * @param int $provider_id The selected provider record id. + * + * @throws Exception When the $services argument type is not array. + * @throws Exception When the $provider_id argument type is not int. + */ + protected function save_services($services, $provider_id) + { + // Validate method arguments. + if ( ! is_array($services)) + { + throw new Exception('Invalid argument type $services: ' . $services); + } + + if ( ! is_numeric($provider_id)) + { + throw new Exception('Invalid argument type $provider_id: ' . $provider_id); + } + + // Save provider services in the database (delete old records and add new). + $this->db->delete('services_providers', ['id_users' => $provider_id]); + foreach ($services as $service_id) + { + $service_provider = [ + 'id_users' => $provider_id, + 'id_services' => $service_id + ]; + $this->db->insert('services_providers', $service_provider); + } + } + + /** + * Update an existing provider record in the database. + * + * @param array $provider Contains the provider data. + * + * @return int Returns the record id. + * + * @throws Exception When the update operation fails. + */ + protected function update($provider) + { + $this->load->helper('general'); + + // Store service and settings (must not be present on the $provider array). + $services = $provider['services']; + unset($provider['services']); + $settings = $provider['settings']; + unset($provider['settings']); + + if (isset($settings['password'])) + { + $salt = $this->db->get_where('user_settings', ['id_users' => $provider['id']])->row()->salt; + $settings['password'] = hash_password($salt, $settings['password']); + } + + // Update provider record. + $this->db->where('id', $provider['id']); + if ( ! $this->db->update('users', $provider)) + { + throw new Exception('Could not update provider record.'); + } + + $this->save_services($services, $provider['id']); + $this->save_settings($settings, $provider['id']); + + // Return record id. + return (int)$provider['id']; + } + + /** + * Delete an existing provider record from the database. + * + * @param int $customer_id The record id to be deleted. + * + * @return bool Returns the delete operation result. + * + * @throws Exception When the provider id value is not int. + */ + public function delete($provider_id) + { + if ( ! is_numeric($provider_id)) + { + throw new Exception('Invalid argument type $provider_id: ' . $provider_id); + } + + $num_rows = $this->db->get_where('users', ['id' => $provider_id])->num_rows(); + if ($num_rows == 0) + { + return FALSE; // Record does not exist in database. + } + + return $this->db->delete('users', ['id' => $provider_id]); + } + + /** + * Get a specific provider record from the database. + * + * @param int $provider_id The id of the record to be returned. + * + * @return array Returns an associative array with the selected record's data. Each key has the same name as the + * database field names. + * + * @throws Exception When the selected record does not exist in database. + */ + public function get_row($provider_id) + { + if ( ! is_numeric($provider_id)) + { + throw new Exception('$provider_id argument is not a valid numeric value: ' . $provider_id); + } + + // Check if selected record exists on database. + if ($this->db->get_where('users', ['id' => $provider_id])->num_rows() == 0) + { + throw new Exception('Selected record does not exist in the database.'); + } + + // Get provider data. + $provider = $this->db->get_where('users', ['id' => $provider_id])->row_array(); + + // Include provider services. + $services = $this->db->get_where('services_providers', + ['id_users' => $provider_id])->result_array(); + $provider['services'] = []; + foreach ($services as $service) + { + $provider['services'][] = $service['id_services']; + } + + // Include provider settings. + $provider['settings'] = $this->db->get_where('user_settings', ['id_users' => $provider_id])->row_array(); + unset($provider['settings']['id_users']); + + // Return provider data array. + return $provider; + } + + /** + * Get a specific field value from the database. + * + * @param string $field_name The field name of the value to be returned. + * @param int $provider_id Record id of the value to be returned. + * + * @return string Returns the selected record value from the database. + * + * @throws Exception When the $field_name argument is not a valid string. + * @throws Exception When the $provider_id is not a valid int. + * @throws Exception When the provider record does not exist in the database. + * @throws Exception When the selected field value is not present on database. + */ + public function get_value($field_name, $provider_id) + { + if ( ! is_numeric($provider_id)) + { + throw new Exception('Invalid argument provided as $provider_id: ' . $provider_id); + } + + if ( ! is_string($field_name)) + { + throw new Exception('$field_name argument is not a string: ' . $field_name); + } + + // Check whether the provider record exists in database. + $result = $this->db->get_where('users', ['id' => $provider_id]); + if ($result->num_rows() == 0) + { + throw new Exception('The record with the $provider_id argument does not exist in ' + . 'the database: ' . $provider_id); + } + + $provider = $result->row_array(); + if ( ! isset($provider[$field_name])) + { + throw new Exception('The given $field_name argument does not exist in the ' + . 'database: ' . $field_name); + } + + return $provider[$field_name]; + } + + /** + * Get all, or specific records from provider's table. + * + * Example: + * + * $this->Model->get_batch('id = ' . $recordId); + * + * + * @param mixed|null $where (OPTIONAL) The WHERE clause of the query to be executed. + * @param mixed|null $order_by + * @param int|null $limit + * @param int|null $offset + * @return array Returns the rows from the database. + */ + public function get_batch($where = NULL, $order_by = NULL, $limit = NULL, $offset = NULL) + { + // CI db class may confuse two where clauses made in the same time, so + // get the role id first and then apply the get_batch() where clause. + $role_id = $this->get_providers_role_id(); + + if ($where !== NULL) + { + $this->db->where($where); + } + + if ($order_by !== NULL) + { + $this->db->order_by($order_by); + } + + $batch = $this->db->get_where('users', ['id_roles' => $role_id], $limit, $offset)->result_array(); + + // Include each provider services and settings. + foreach ($batch as &$provider) + { + // Services + $services = $this->db->get_where('services_providers', + ['id_users' => $provider['id']])->result_array(); + $provider['services'] = []; + foreach ($services as $service) + { + $provider['services'][] = $service['id_services']; + } + + // Settings + $provider['settings'] = $this->db->get_where('user_settings', + ['id_users' => $provider['id']])->row_array(); + unset($provider['settings']['id_users']); + } + + // Return provider records in an array. + return $batch; + } + + /** + * Get the available system providers. + * + * This method returns the available providers and the services that can provide. + * + * @return array Returns an array with the providers data. + */ + public function get_available_providers() + { + // Get provider records from database. + $this->db + ->select('users.*') + ->from('users') + ->join('roles', 'roles.id = users.id_roles', 'inner') + ->where('roles.slug', DB_SLUG_PROVIDER) + ->order_by('first_name ASC, last_name ASC, email ASC'); + + $providers = $this->db->get()->result_array(); + + // Include each provider services and settings. + foreach ($providers as &$provider) + { + // Services + $services = $this->db->get_where('services_providers', + ['id_users' => $provider['id']])->result_array(); + + $provider['services'] = []; + foreach ($services as $service) + { + $provider['services'][] = $service['id_services']; + } + + // Settings + $provider['settings'] = $this->db->get_where('user_settings', + ['id_users' => $provider['id']])->row_array(); + unset($provider['settings']['username']); + unset($provider['settings']['password']); + unset($provider['settings']['salt']); + } + + // Return provider records. + return $providers; + } + + /** + * Get a providers setting from the database. + * + * @param string $setting_name The setting name that is going to be returned. + * @param int $provider_id The selected provider id. + * + * @return string Returns the value of the selected user setting. + */ + public function get_setting($setting_name, $provider_id) + { + $provider_settings = $this->db->get_where('user_settings', ['id_users' => $provider_id])->row_array(); + + return $provider_settings[$setting_name]; + } + + /** + * Save the provider working plan exception. + * + * @param string $date The working plan exception date (in YYYY-MM-DD format). + * @param array $working_plan_exception Contains the working plan exception information ("start", "end" and "breaks" + * properties). + * @param int $provider_id The selected provider record id. + * + * @return bool Return if the new working plan exceptions is correctly saved to DB. + * + * @throws Exception If start time is after the end time. + * @throws Exception If $provider_id argument is invalid. + */ + public function save_working_plan_exception($date, $working_plan_exception, $provider_id) + { + // Validate the working plan exception data. + $start = date('H:i', strtotime($working_plan_exception['start'])); + $end = date('H:i', strtotime($working_plan_exception['end'])); + + if ($start > $end) + { + throw new Exception('Working plan exception "start" must be prior to "end".'); + } + + // Make sure the provider record exists. + $conditions = [ + 'id' => $provider_id, + 'id_roles' => $this->db->get_where('roles', ['slug' => DB_SLUG_PROVIDER])->row()->id + ]; + + if ($this->db->get_where('users', $conditions)->num_rows() === 0) + { + throw new Exception('Provider record was not found in database: ' . $provider_id); + } + + // Add record to database. + $working_plan_exceptions = json_decode($this->get_setting('working_plan_exceptions', $provider_id), TRUE); + + if (!isset($working_plan_exception['breaks'])) + { + $working_plan_exception['breaks'] = []; + } + + $working_plan_exceptions[$date] = $working_plan_exception; + + return $this->set_setting( + 'working_plan_exceptions', + json_encode($working_plan_exceptions), + $provider_id + ); + } + + /** + * Delete a provider working plan exception. + * + * @param string $date The working plan exception date (in YYYY-MM-DD format). + * @param int $provider_id The selected provider record id. + * + * @return bool Return if the new working plan exceptions is correctly deleted from DB. + * + * @throws Exception If $provider_id argument is invalid. + */ + public function delete_working_plan_exception($date, $provider_id) + { + $provider = $this->get_row($provider_id); + + $working_plan_exceptions = json_decode($provider['settings']['working_plan_exceptions'], TRUE); + + if ( ! isset($working_plan_exceptions[$date])) + { + return TRUE; // The selected date does not exist in provider's settings. + } + + unset($working_plan_exceptions[$date]); + + return $this->set_setting( + 'working_plan_exceptions', + json_encode(empty($working_plan_exceptions) ? new stdClass() : $working_plan_exceptions), + $provider_id + ); + } +} diff --git a/application/models/Roles_model.php b/application/models/Roles_model.php new file mode 100644 index 00000000..e7b7caa5 --- /dev/null +++ b/application/models/Roles_model.php @@ -0,0 +1,89 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +/** + * Roles Model + * + * @property CI_DB_query_builder $db + * @property CI_Loader $load + * + * @package Models + */ +class Roles_Model extends CI_Model { + /** + * Get the record id of a particular role. + * + * @param string $role_slug The selected role slug. Slugs are defined in the "application/config/constants.php" file. + * + * @return int Returns the database id of the roles record. + */ + public function get_role_id($role_slug) + { + return $this->db->get_where('roles', ['slug' => $role_slug])->row()->id; + } + + /** + * Returns all the privileges (bool values) of a role slug. + * + * The privilege numbers are converted into bool values of the four main actions (view, add, edit, delete). By + * checking each value you can know if the user is able to perform this action. + * + * @param string $slug The role slug. + * + * @return array Returns the privilege value. + */ + public function get_privileges($slug) + { + $privileges = $this->db->get_where('roles', ['slug' => $slug])->row_array(); + unset($privileges['id'], $privileges['name'], $privileges['slug'], $privileges['is_admin']); + + // Convert the int values to bool so that is easier to check whether a + // user has the required privileges for a specific action. + foreach ($privileges as &$value) + { + $privileges_number = $value; + + $value = [ + 'view' => FALSE, + 'add' => FALSE, + 'edit' => FALSE, + 'delete' => FALSE + ]; + + if ($privileges_number > 0) + { + if ((int)($privileges_number / PRIV_DELETE) == 1) + { + $value['delete'] = TRUE; + $privileges_number -= PRIV_DELETE; + } + + if ((int)($privileges_number / PRIV_EDIT) == 1) + { + $value['edit'] = TRUE; + $privileges_number -= PRIV_EDIT; + } + + if ((int)($privileges_number / PRIV_ADD) == 1) + { + $value['add'] = TRUE; + $privileges_number -= PRIV_ADD; + } + + $value['view'] = TRUE; + } + } + + return $privileges; + } +} diff --git a/application/models/Secretaries_model.php b/application/models/Secretaries_model.php new file mode 100644 index 00000000..861a20a0 --- /dev/null +++ b/application/models/Secretaries_model.php @@ -0,0 +1,555 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +/** + * Secretaries Model + * + * Handles the db actions that have to do with secretaries. + * + * @property CI_DB_query_builder $db + * @property CI_Loader $load + * + * @package Models + */ +class Secretaries_Model extends CI_Model { + /** + * Add (insert or update) a secretary user record into database. + * + * @param array $secretary Contains the secretary user data. + * + * @return int Returns the record id. + * + * @throws Exception When the secretary data are invalid (see validate() method). + */ + public function add($secretary) + { + $this->validate($secretary); + + if ($this->exists($secretary) && ! isset($secretary['id'])) + { + $secretary['id'] = $this->find_record_id($secretary); + } + + if ( ! isset($secretary['id'])) + { + $secretary['id'] = $this->insert($secretary); + } + else + { + $secretary['id'] = $this->update($secretary); + } + + return (int)$secretary['id']; + } + + /** + * Validate secretary user data before add() operation is executed. + * + * @param array $secretary Contains the secretary user data. + * + * @return bool Returns the validation result. + * + * @throws Exception If secretary validation fails. + */ + public function validate($secretary) + { + $this->load->helper('data_validation'); + + // If a record id is provided then check whether the record exists in the database. + if (isset($secretary['id'])) + { + $num_rows = $this->db->get_where('users', ['id' => $secretary['id']]) + ->num_rows(); + if ($num_rows == 0) + { + throw new Exception('Given secretary id does not exist in database: ' . $secretary['id']); + } + } + + // Validate 'providers' value data type (must be array) + if (isset($secretary['providers']) && ! is_array($secretary['providers'])) + { + throw new Exception('Secretary providers value is not an array.'); + } + + // Validate required fields integrity. + if ( ! isset($secretary['last_name']) + || ! isset($secretary['email']) + || ! isset($secretary['phone_number'])) + { + throw new Exception('Not all required fields are provided: ' . print_r($secretary, TRUE)); + } + + // Validate secretary email address. + if ( ! filter_var($secretary['email'], FILTER_VALIDATE_EMAIL)) + { + throw new Exception('Invalid email address provided: ' . $secretary['email']); + } + + // Check if username exists. + if (isset($secretary['settings']['username'])) + { + $user_id = (isset($secretary['id'])) ? $secretary['id'] : ''; + if ( ! $this->validate_username($secretary['settings']['username'], $user_id)) + { + throw new Exception ('Username already exists. Please select a different ' + . 'username for this record.'); + } + } + + // Validate secretary password. + if (isset($secretary['settings']['password'])) + { + if (strlen($secretary['settings']['password']) < MIN_PASSWORD_LENGTH) + { + throw new Exception('The user password must be at least ' + . MIN_PASSWORD_LENGTH . ' characters long.'); + } + } + + // Validate calendar view mode. + if (isset($secretary['settings']['calendar_view']) && ($secretary['settings']['calendar_view'] !== CALENDAR_VIEW_DEFAULT + && $secretary['settings']['calendar_view'] !== CALENDAR_VIEW_TABLE)) + { + throw new Exception('The calendar view setting must be either "' . CALENDAR_VIEW_DEFAULT + . '" or "' . CALENDAR_VIEW_TABLE . '", given: ' . $secretary['settings']['calendar_view']); + } + + // When inserting a record the email address must be unique. + $secretary_id = (isset($secretary['id'])) ? $secretary['id'] : ''; + + $num_rows = $this->db + ->select('*') + ->from('users') + ->join('roles', 'roles.id = users.id_roles', 'inner') + ->where('roles.slug', DB_SLUG_SECRETARY) + ->where('users.email', $secretary['email']) + ->where('users.id <>', $secretary_id) + ->get() + ->num_rows(); + + if ($num_rows > 0) + { + throw new Exception('Given email address belongs to another secretary record. ' + . 'Please use a different email.'); + } + + return TRUE; + } + + /** + * Validate Records Username + * + * @param string $username The provider records username. + * @param int $user_id The user record id. + * + * @return bool Returns the validation result. + */ + public function validate_username($username, $user_id) + { + $num_rows = $this->db->get_where('user_settings', + ['username' => $username, 'id_users <> ' => $user_id])->num_rows(); + return ($num_rows > 0) ? FALSE : TRUE; + } + + /** + * Check whether a particular secretary record exists in the database. + * + * @param array $secretary Contains the secretary data. The 'email' value is required to be present at the moment. + * + * @return bool Returns whether the record exists or not. + * + * @throws Exception When the 'email' value is not present on the $secretary argument. + */ + public function exists($secretary) + { + if ( ! isset($secretary['email'])) + { + throw new Exception('Secretary email is not provided: ' . print_r($secretary, TRUE)); + } + + // This method shouldn't depend on another method of this class. + $num_rows = $this->db + ->select('*') + ->from('users') + ->join('roles', 'roles.id = users.id_roles', 'inner') + ->where('users.email', $secretary['email']) + ->where('roles.slug', DB_SLUG_SECRETARY) + ->get()->num_rows(); + + return ($num_rows > 0) ? TRUE : FALSE; + } + + /** + * Find the database record id of a secretary. + * + * @param array $secretary Contains the secretary data. The 'email' value is required in order to find the record id. + * + * @return int Returns the record id + * + * @throws Exception When the 'email' value is not present on the $secretary array. + */ + public function find_record_id($secretary) + { + if ( ! isset($secretary['email'])) + { + throw new Exception('Secretary email was not provided: ' . print_r($secretary, TRUE)); + } + + $result = $this->db + ->select('users.id') + ->from('users') + ->join('roles', 'roles.id = users.id_roles', 'inner') + ->where('users.email', $secretary['email']) + ->where('roles.slug', DB_SLUG_SECRETARY) + ->get(); + + if ($result->num_rows() == 0) + { + throw new Exception('Could not find secretary record id.'); + } + + return (int)$result->row()->id; + } + + /** + * Insert a new secretary record into the database. + * + * @param array $secretary Contains the secretary data. + * + * @return int Returns the new record id. + * + * @throws Exception When the insert operation fails. + */ + protected function insert($secretary) + { + $this->load->helper('general'); + + $providers = $secretary['providers']; + unset($secretary['providers']); + $settings = $secretary['settings']; + unset($secretary['settings']); + + $secretary['id_roles'] = $this->get_secretary_role_id(); + + if ( ! $this->db->insert('users', $secretary)) + { + throw new Exception('Could not insert secretary into the database.'); + } + + $secretary['id'] = (int)$this->db->insert_id(); + $settings['salt'] = generate_salt(); + $settings['password'] = hash_password($settings['salt'], $settings['password']); + + $this->save_providers($providers, $secretary['id']); + $this->save_settings($settings, $secretary['id']); + + return $secretary['id']; + } + + /** + * Get the secretary users role id. + * + * @return int Returns the role record id. + */ + public function get_secretary_role_id() + { + return (int)$this->db->get_where('roles', ['slug' => DB_SLUG_SECRETARY])->row()->id; + } + + /** + * Save a secretary handling users. + * + * @param array $providers Contains the provider ids that are handled by the secretary. + * @param int $secretary_id The selected secretary record. + * + * @throws Exception If $providers argument is invalid. + */ + protected function save_providers($providers, $secretary_id) + { + if ( ! is_array($providers)) + { + throw new Exception('Invalid argument given $providers: ' . print_r($providers, TRUE)); + } + + // Delete old connections + $this->db->delete('secretaries_providers', ['id_users_secretary' => $secretary_id]); + + if (count($providers) > 0) + { + foreach ($providers as $provider_id) + { + $this->db->insert('secretaries_providers', [ + 'id_users_secretary' => $secretary_id, + 'id_users_provider' => $provider_id + ]); + } + } + } + + /** + * Save the secretary settings (used from insert or update operation). + * + * @param array $settings Contains the setting values. + * @param int $secretary_id Record id of the secretary. + * + * @throws Exception If $secretary_id argument is invalid. + * @throws Exception If $settings argument is invalid. + */ + protected function save_settings($settings, $secretary_id) + { + if ( ! is_numeric($secretary_id)) + { + throw new Exception('Invalid $secretary_id argument given:' . $secretary_id); + } + + if (count($settings) == 0 || ! is_array($settings)) + { + throw new Exception('Invalid $settings argument given:' . print_r($settings, TRUE)); + } + + // Check if the setting record exists in db. + $num_rows = $this->db->get_where('user_settings', + ['id_users' => $secretary_id])->num_rows(); + if ($num_rows == 0) + { + $this->db->insert('user_settings', ['id_users' => $secretary_id]); + } + + foreach ($settings as $name => $value) + { + $this->set_setting($name, $value, $secretary_id); + } + } + + /** + * Set a provider's setting value in the database. + * + * The provider and settings record must already exist. + * + * @param string $setting_name The setting's name. + * @param string $value The setting's value. + * @param int $secretary_id The selected provider id. + */ + public function set_setting($setting_name, $value, $secretary_id) + { + $this->db->where(['id_users' => $secretary_id]); + return $this->db->update('user_settings', [$setting_name => $value]); + } + + /** + * Update an existing secretary record in the database. + * + * @param array $secretary Contains the secretary record data. + * + * @return int Returns the record id. + * + * @throws Exception When the update operation fails. + */ + protected function update($secretary) + { + $this->load->helper('general'); + + $providers = $secretary['providers']; + unset($secretary['providers']); + $settings = $secretary['settings']; + unset($secretary['settings']); + + if (isset($settings['password'])) + { + $salt = $this->db->get_where('user_settings', ['id_users' => $secretary['id']])->row()->salt; + $settings['password'] = hash_password($salt, $settings['password']); + } + + $this->db->where('id', $secretary['id']); + if ( ! $this->db->update('users', $secretary)) + { + throw new Exception('Could not update secretary record.'); + } + + $this->save_providers($providers, $secretary['id']); + $this->save_settings($settings, $secretary['id']); + + return (int)$secretary['id']; + } + + /** + * Delete an existing secretary record from the database. + * + * @param int $secretary_id The secretary record id to be deleted. + * + * @return bool Returns the delete operation result. + * + * @throws Exception When the $secretary_id is not a valid int value. + */ + public function delete($secretary_id) + { + if ( ! is_numeric($secretary_id)) + { + throw new Exception('Invalid argument type $secretary_id: ' . $secretary_id); + } + + $num_rows = $this->db->get_where('users', ['id' => $secretary_id])->num_rows(); + if ($num_rows == 0) + { + return FALSE; // Record does not exist in database. + } + + return $this->db->delete('users', ['id' => $secretary_id]); + } + + /** + * Get a specific secretary record from the database. + * + * @param int $secretary_id The id of the record to be returned. + * + * @return array Returns an array with the secretary user data. + * + * @throws Exception When the $secretary_id is not a valid int value. + * @throws Exception When given record id does not exist in the database. + */ + public function get_row($secretary_id) + { + if ( ! is_numeric($secretary_id)) + { + throw new Exception('$secretary_id argument is not a valid numeric value: ' . $secretary_id); + } + + // Check if record exists + if ($this->db->get_where('users', ['id' => $secretary_id])->num_rows() == 0) + { + throw new Exception('The given secretary id does not match a record in the database.'); + } + + $secretary = $this->db->get_where('users', ['id' => $secretary_id])->row_array(); + + $secretary_providers = $this->db->get_where('secretaries_providers', + ['id_users_secretary' => $secretary['id']])->result_array(); + $secretary['providers'] = []; + foreach ($secretary_providers as $secretary_provider) + { + $secretary['providers'][] = $secretary_provider['id_users_provider']; + } + + $secretary['settings'] = $this->db->get_where('user_settings', + ['id_users' => $secretary['id']])->row_array(); + unset($secretary['settings']['id_users'], $secretary['settings']['salt']); + + return $secretary; + } + + /** + * Get a specific field value from the database. + * + * @param string $field_name The field name of the value to be returned. + * @param int $secretary_id Record id of the value to be returned. + * + * @return string Returns the selected record value from the database. + * + * @throws Exception When the $field_name argument is not a valid string. + * @throws Exception When the $secretary_id is not a valid int. + * @throws Exception When the secretary record does not exist in the database. + * @throws Exception When the selected field value is not present on database. + */ + public function get_value($field_name, $secretary_id) + { + if ( ! is_string($field_name)) + { + throw new Exception('$field_name argument is not a string: ' . $field_name); + } + + if ( ! is_numeric($secretary_id)) + { + throw new Exception('$secretary_id argument is not a valid numeric value: ' . $secretary_id); + } + + // Check whether the secretary record exists. + $result = $this->db->get_where('users', ['id' => $secretary_id]); + if ($result->num_rows() == 0) + { + throw new Exception('The record with the given id does not exist in the ' + . 'database: ' . $secretary_id); + } + + // Check if the required field name exist in database. + $provider = $result->row_array(); + if ( ! isset($provider[$field_name])) + { + throw new Exception('The given $field_name argument does not exist in the ' + . 'database: ' . $field_name); + } + + return $provider[$field_name]; + } + + /** + * Get all, or specific secretary records from database. + * + * @param mixed|null $where (OPTIONAL) The WHERE clause of the query to be executed. Use this to get + * specific secretary records. + * @param mixed|null $order_by + * @param int|null $limit + * @param int|null $offset + * @return array Returns an array with secretary records. + */ + public function get_batch($where = NULL, $order_by = NULL, $limit = NULL, $offset = NULL) + { + $role_id = $this->get_secretary_role_id(); + + if ($where !== NULL) + { + $this->db->where($where); + } + + if ($order_by !== NULL) + { + $this->db->order_by($order_by); + } + + $batch = $this->db->get_where('users', ['id_roles' => $role_id], $limit, $offset)->result_array(); + + // Include every secretary providers. + foreach ($batch as &$secretary) + { + $secretary_providers = $this->db->get_where('secretaries_providers', + ['id_users_secretary' => $secretary['id']])->result_array(); + + $secretary['providers'] = []; + foreach ($secretary_providers as $secretary_provider) + { + $secretary['providers'][] = $secretary_provider['id_users_provider']; + } + + $secretary['settings'] = $this->db->get_where('user_settings', + ['id_users' => $secretary['id']])->row_array(); + unset($secretary['settings']['id_users']); + } + + return $batch; + } + + /** + * Get a providers setting from the database. + * + * @param string $setting_name The setting name that is going to be returned. + * @param int $secretary_id The selected provider id. + * + * @return string Returns the value of the selected user setting. + */ + public function get_setting($setting_name, $secretary_id) + { + $provider_settings = $this->db->get_where('user_settings', + ['id_users' => $secretary_id])->row_array(); + return $provider_settings[$setting_name]; + } +} diff --git a/application/models/Services_model.php b/application/models/Services_model.php new file mode 100644 index 00000000..df6d101a --- /dev/null +++ b/application/models/Services_model.php @@ -0,0 +1,490 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +/** + * Services Model + * + * @property CI_DB_query_builder $db + * @property CI_Loader $load + * + * @package Models + */ +class Services_Model extends CI_Model { + /** + * Add (insert or update) a service record on the database + * + * @param array $service Contains the service data. If an 'id' value is provided then the record will be updated. + * + * @return int Returns the record id. + * @throws Exception + */ + public function add($service) + { + $this->validate($service); + + if ( ! isset($service['id'])) + { + $service['id'] = $this->insert($service); + } + else + { + $this->update($service); + } + + return (int)$service['id']; + } + + /** + * Validate a service record data. + * + * @param array $service Contains the service data. + * + * @return bool Returns the validation result. + * + * @throws Exception If service validation fails. + */ + public function validate($service) + { + $this->load->helper('data_validation'); + + // If record id is provided we need to check whether the record exists + // in the database. + if (isset($service['id'])) + { + $num_rows = $this->db->get_where('services', ['id' => $service['id']]) + ->num_rows(); + if ($num_rows == 0) + { + throw new Exception('Provided service id does not exist in the database.'); + } + } + + // Check if service category id is valid (only when present). + if ( ! empty($service['id_service_categories'])) + { + $num_rows = $this->db->get_where('service_categories', + ['id' => $service['id_service_categories']])->num_rows(); + if ($num_rows == 0) + { + throw new Exception('Provided service category id does not exist in database.'); + } + } + + // Check for required fields + if ($service['name'] == '') + { + throw new Exception('Not all required service fields where provided: ' + . print_r($service, TRUE)); + } + + // Duration must be int + if ($service['duration'] !== NULL) + { + if ( ! is_numeric($service['duration'])) + { + throw new Exception('Service duration is not numeric.'); + } + } + + if ($service['price'] !== NULL) + { + if ( ! is_numeric($service['price'])) + { + throw new Exception('Service price is not numeric.'); + } + } + + // Availabilities type must have the correct value. + if ($service['availabilities_type'] !== NULL && $service['availabilities_type'] !== AVAILABILITIES_TYPE_FLEXIBLE + && $service['availabilities_type'] !== AVAILABILITIES_TYPE_FIXED) + { + throw new Exception('Service availabilities type must be either ' . AVAILABILITIES_TYPE_FLEXIBLE + . ' or ' . AVAILABILITIES_TYPE_FIXED . ' (given ' . $service['availabilities_type'] . ')'); + } + + if ($service['attendants_number'] !== NULL && ( ! is_numeric($service['attendants_number']) + || $service['attendants_number'] < 1)) + { + throw new Exception('Service attendants number must be numeric and greater or equal to one: ' + . $service['attendants_number']); + } + + return TRUE; + } + + /** + * Insert service record into database. + * + * @param array $service Contains the service record data. + * + * @return int Returns the new service record id. + * + * @throws Exception If service record could not be inserted. + */ + protected function insert($service) + { + if ( ! $this->db->insert('services', $service)) + { + throw new Exception('Could not insert service record.'); + } + return (int)$this->db->insert_id(); + } + + /** + * Update service record. + * + * @param array $service Contains the service data. The record id needs to be included in the array. + * + * @throws Exception If service record could not be updated. + */ + protected function update($service) + { + $this->db->where('id', $service['id']); + if ( ! $this->db->update('services', $service)) + { + throw new Exception('Could not update service record'); + } + } + + /** + * Checks whether an service record already exists in the database. + * + * @param array $service Contains the service data. Name, duration and price values are mandatory in order to + * perform the checks. + * + * @return bool Returns whether the service record exists. + * + * @throws Exception If required fields are missing. + */ + public function exists($service) + { + if ( ! isset($service['name']) + || ! isset($service['duration']) + || ! isset($service['price'])) + { + throw new Exception('Not all service fields are provided in order to check whether ' + . 'a service record already exists: ' . print_r($service, TRUE)); + } + + $num_rows = $this->db->get_where('services', [ + 'name' => $service['name'], + 'duration' => $service['duration'], + 'price' => $service['price'] + ])->num_rows(); + + return ($num_rows > 0) ? TRUE : FALSE; + } + + /** + * Get the record id of an existing record. + * + * NOTICE: The record must exist, otherwise an exception will be raised. + * + * @param array $service Contains the service record data. Name, duration and price values are mandatory for this + * method to complete. + * + * @throws Exception If required fields are missing. + * @throws Exception If requested service was not found. + */ + public function find_record_id($service) + { + if ( ! isset($service['name']) + || ! isset($service['duration']) + || ! isset($service['price'])) + { + throw new Exception('Not all required fields where provided in order to find the ' + . 'service record id.'); + } + + $result = $this->db->get_where('services', [ + 'name' => $service['name'], + 'duration' => $service['duration'], + 'price' => $service['price'] + ]); + + if ($result->num_rows() == 0) + { + throw new Exception('Could not find service record id'); + } + + return $result->row()->id; + } + + /** + * Delete a service record from database. + * + * @param int $service_id Record id to be deleted. + * + * @return bool Returns the delete operation result. + * + * @throws Exception If $service_id argument is invalid. + */ + public function delete($service_id) + { + if ( ! is_numeric($service_id)) + { + throw new Exception('Invalid argument type $service_id (value:"' . $service_id . '"'); + } + + $num_rows = $this->db->get_where('services', ['id' => $service_id])->num_rows(); + if ($num_rows == 0) + { + return FALSE; // Record does not exist + } + + return $this->db->delete('services', ['id' => $service_id]); + } + + /** + * Get a specific row from the services db table. + * + * @param int $service_id The record's id to be returned. + * + * @return array Returns an associative array with the selected record's data. Each key has the same name as the + * database field names. + * + * @throws Exception If $service_id argument is not valid. + */ + public function get_row($service_id) + { + if ( ! is_numeric($service_id)) + { + throw new Exception('$service_id argument is not an numeric (value: "' . $service_id . '")'); + } + return $this->db->get_where('services', ['id' => $service_id])->row_array(); + } + + /** + * Get a specific field value from the database. + * + * @param string $field_name The field name of the value to be + * returned. + * @param int $service_id The selected record's id. + * + * @return string Returns the records value from the database. + * + * @throws Exception If $service_id argument is invalid. + * @throws Exception If $field_name argument is invalid. + * @throws Exception if requested service does not exist in the database. + * @throws Exception If requested field name does not exist in the database. + */ + public function get_value($field_name, $service_id) + { + if ( ! is_numeric($service_id)) + { + throw new Exception('Invalid argument provided as $service_id: ' . $service_id); + } + + if ( ! is_string($field_name)) + { + throw new Exception('$field_name argument is not a string: ' . $field_name); + } + + if ($this->db->get_where('services', ['id' => $service_id])->num_rows() == 0) + { + throw new Exception('The record with the $service_id argument does not exist in the database: ' . $service_id); + } + + $row_data = $this->db->get_where('services', ['id' => $service_id])->row_array(); + if ( ! isset($row_data[$field_name])) + { + throw new Exception('The given $field_name argument does not exist in the database: ' . $field_name); + } + + $setting = $this->db->get_where('services', ['id' => $service_id])->row_array(); + return $setting[$field_name]; + } + + /** + * Get all, or specific records from service's table. + * + * @param string $whereClause (OPTIONAL) The WHERE clause of + * the query to be executed. DO NOT INCLUDE 'WHERE' KEYWORD. + * + * @return array Returns the rows from the database. + * @example $this->Model->getBatch('id = ' . $recordId); + * + */ + public function get_batch($where = NULL, $order_by = NULL, $limit = NULL, $offset = NULL) + { + if ($where !== NULL) + { + $this->db->where($where); + } + + if ($order_by !== NULL) + { + $this->db->order_by($order_by); + } + + return $this->db->get('services', $limit, $offset)->result_array(); + } + + /** + * This method returns all the services from the database. + * + * @return array Returns an object array with all the database services. + */ + public function get_available_services() + { + $this->db->distinct(); + return $this->db + ->select('services.*, service_categories.name AS category_name, ' + . 'service_categories.id AS category_id') + ->from('services') + ->join('services_providers', + 'services_providers.id_services = services.id', 'inner') + ->join('service_categories', + 'service_categories.id = services.id_service_categories', 'left') + ->order_by('name ASC') + ->get()->result_array(); + } + + /** + * Add (insert or update) a service category record into database. + * + * @param array $category Contains the service category data. + * + * @return int Returns the record ID. + * + * @throws Exception If service category data are invalid. + */ + public function add_category($category) + { + if ( ! $this->validate_category($category)) + { + throw new Exception('Service category data are invalid.'); + } + + if ( ! isset($category['id'])) + { + $this->db->insert('service_categories', $category); + $category['id'] = $this->db->insert_id(); + } + else + { + $this->db->where('id', $category['id']); + $this->db->update('service_categories', $category); + } + + return (int)$category['id']; + } + + /** + * Validate a service category record data. This method must be used before adding + * a service category record into database in order to secure the record integrity. + * + * @param array $category Contains the service category data. + * + * @return bool Returns the validation result. + * + * @throws Exception If required fields are missing. + */ + public function validate_category($category) + { + try + { + // Required Fields + if ( ! isset($category['name'])) + { + throw new Exception('Not all required fields where provided '); + } + + if ($category['name'] == '' || $category['name'] == NULL) + { + throw new Exception('Required fields cannot be empty or null ($category: ' + . print_r($category, TRUE) . ')'); + } + + return TRUE; + } + catch (Exception $exception) + { + return FALSE; + } + } + + /** + * Delete a service category record from the database. + * + * @param int $category_id Record id to be deleted. + * + * @return bool Returns the delete operation result. + * + * @throws Exception if Service category record was not found. + */ + public function delete_category($category_id) + { + if ( ! is_numeric($category_id)) + { + throw new Exception('Invalid argument given for $category_id: ' . $category_id); + } + + $num_rows = $this->db->get_where('service_categories', ['id' => $category_id]) + ->num_rows(); + if ($num_rows == 0) + { + throw new Exception('Service category record not found in database.'); + } + + $this->db->where('id', $category_id); + return $this->db->delete('service_categories'); + } + + /** + * Get a service category record data. + * + * @param int $category_id Record id to be retrieved. + * + * @return array Returns the record data from the database. + * + * @throws Exception If $category_id argument is invalid. + * @throws Exception If service category record does not exist. + */ + public function get_category($category_id) + { + if ( ! is_numeric($category_id)) + { + throw new Exception('Invalid argument type given $category_id: ' . $category_id); + } + + $result = $this->db->get_where('service_categories', ['id' => $category_id]); + + if ($result->num_rows() == 0) + { + throw new Exception('Service category record does not exist.'); + } + + return $result->row_array(); + } + + /** + * Get all service category records from database. + * + * @return array Returns an array that contains all the service category records. + */ + public function get_all_categories($where = NULL, $order_by = NULL, $limit = NULL, $offset = NULL) + { + if ($where !== NULL) + { + $this->db->where($where); + } + + if ($order_by !== NULL) + { + $this->db->order_by($order_by); + } + + return $this->db->get('service_categories', $limit, $offset)->result_array(); + } +} diff --git a/application/models/Settings_model.php b/application/models/Settings_model.php new file mode 100644 index 00000000..396f9045 --- /dev/null +++ b/application/models/Settings_model.php @@ -0,0 +1,164 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +/** + * Settings Model + * + * @property CI_DB_query_builder $db + * @property CI_Loader $load + * + * @package Models + */ +class Settings_Model extends CI_Model { + /** + * Get setting value from database. + * + * This method returns a system setting from the database. + * + * @param string $name The database setting name. + * + * @return string Returns the database value for the selected setting. + * + * @throws Exception If the $name argument is invalid. + * @throws Exception If the requested $name setting does not exist in the database. + */ + public function get_setting($name) + { + if ( ! is_string($name)) + { // Check argument type. + throw new Exception('$name argument is not a string: ' . $name); + } + + if ($this->db->get_where('settings', ['name' => $name])->num_rows() == 0) + { // Check if setting exists in db. + throw new Exception('$name setting does not exist in database: ' . $name); + } + + $query = $this->db->get_where('settings', ['name' => $name]); + $setting = $query->num_rows() > 0 ? $query->row() : ''; + return $setting->value; + } + + /** + * This method sets the value for a specific setting on the database. + * + * If the setting doesn't exist, it is going to be created, otherwise updated. + * + * @param string $name The setting name. + * @param string $value The setting value. + * + * @return int Returns the setting database id. + * + * @throws Exception If $name argument is invalid. + * @throws Exception If the save operation fails. + */ + public function set_setting($name, $value) + { + if ( ! is_string($name)) + { + throw new Exception('$name argument is not a string: ' . $name); + } + + $query = $this->db->get_where('settings', ['name' => $name]); + if ($query->num_rows() > 0) + { + // Update setting + if ( ! $this->db->update('settings', ['value' => $value], ['name' => $name])) + { + throw new Exception('Could not update database setting.'); + } + $setting_id = (int)$this->db->get_where('settings', ['name' => $name])->row()->id; + } + else + { + // Insert setting + $insert_data = [ + 'name' => $name, + 'value' => $value + ]; + if ( ! $this->db->insert('settings', $insert_data)) + { + throw new Exception('Could not insert database setting'); + } + $setting_id = (int)$this->db->insert_id(); + } + + return $setting_id; + } + + /** + * Remove a setting from the database. + * + * @param string $name The setting name to be removed. + * + * @return bool Returns the delete operation result. + * + * @throws Exception If the $name argument is invalid. + */ + public function remove_setting($name) + { + if ( ! is_string($name)) + { + throw new Exception('$name is not a string: ' . $name); + } + + if ($this->db->get_where('settings', ['name' => $name])->num_rows() == 0) + { + return FALSE; // There is no such setting. + } + + return $this->db->delete('settings', ['name' => $name]); + } + + /** + * Saves all the system settings into the database. + * + * This method is useful when trying to save all the system settings at once instead of + * saving them one by one. + * + * @param array $settings Contains all the system settings. + * + * @return bool Returns the save operation result. + * + * @throws Exception When the update operation won't work for a specific setting. + */ + public function save_settings($settings) + { + if ( ! is_array($settings)) + { + throw new Exception('$settings argument is invalid: ' . print_r($settings, TRUE)); + } + + foreach ($settings as $setting) + { + $this->db->where('name', $setting['name']); + if ( ! $this->db->update('settings', ['value' => $setting['value']])) + { + throw new Exception('Could not save setting (' . $setting['name'] + . ' - ' . $setting['value'] . ')'); + } + } + + return TRUE; + } + + /** + * Returns all the system settings at once. + * + * @return array Array of all the system settings stored in the 'settings' table. + */ + public function get_settings() + { + return $this->db->get('settings')->result_array(); + } +} diff --git a/application/models/User_model.php b/application/models/User_model.php new file mode 100644 index 00000000..417734aa --- /dev/null +++ b/application/models/User_model.php @@ -0,0 +1,210 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +/** + * User Model + * + * Contains current user's methods. + * + * @property CI_DB_query_builder $db + * @property CI_Loader $load + * + * @package Models + */ +class User_Model extends CI_Model { + /** + * Returns the user from the database for the "settings" page. + * + * @param int $user_id User record id. + * + * @return array Returns an array with user data. + */ + public function get_user($user_id) + { + $user = $this->db->get_where('users', ['id' => $user_id])->row_array(); + $user['settings'] = $this->db->get_where('user_settings', ['id_users' => $user_id])->row_array(); + unset($user['settings']['id_users']); + return $user; + } + + /** + * This method saves the user record into the database (used in backend settings page). + * + * @param array $user Contains the current users data. + * + * @return bool Returns the operation result. + */ + public function save_user($user) + { + $user_settings = $user['settings']; + $user_settings['id_users'] = $user['id']; + unset($user['settings']); + + // Prepare user password (hash). + if (isset($user_settings['password'])) + { + $this->load->helper('general'); + $salt = $this->db->get_where('user_settings', ['id_users' => $user['id']])->row()->salt; + $user_settings['password'] = hash_password($salt, $user_settings['password']); + } + + if ( ! $this->db->update('users', $user, ['id' => $user['id']])) + { + return FALSE; + } + + if ( ! $this->db->update('user_settings', $user_settings, ['id_users' => $user['id']])) + { + return FALSE; + } + + return TRUE; + } + + /** + * Performs the check of the given user credentials. + * + * @param string $username Given user's name. + * @param string $password Given user's password (not hashed yet). + * + * @return array|null Returns the session data of the logged in user or null on failure. + */ + public function check_login($username, $password) + { + $this->load->helper('general'); + $salt = $this->get_salt($username); + $password = hash_password($salt, $password); + + $user_settings = $this->db->get_where('user_settings', [ + 'username' => $username, + 'password' => $password + ])->row_array(); + + if (empty($user_settings)) + { + return NULL; + } + + $user = $this->db->get_where('users', ['id' => $user_settings['id_users']])->row_array(); + + if (empty($user)) + { + return NULL; + } + + $role = $this->db->get_where('roles', ['id' => $user['id_roles']])->row_array(); + + if (empty($role)) + { + return NULL; + } + + $this->load->library('timezones'); + + $default_timezone = $this->timezones->get_default_timezone(); + + return [ + 'user_id' => $user['id'], + 'user_email' => $user['email'], + 'username' => $username, + 'timezone' => isset($user['timezone']) ? $user['timezone'] : $default_timezone, + 'role_slug' => $role['slug'], + ]; + } + + /** + * Retrieve user's salt from database. + * + * @param string $username This will be used to find the user record. + * + * @return string Returns the salt db value. + */ + public function get_salt($username) + { + $user = $this->db->get_where('user_settings', ['username' => $username])->row_array(); + return ($user) ? $user['salt'] : ''; + } + + /** + * Get the given user's display name (first + last name). + * + * @param int $user_id The given user record id. + * + * @return string Returns the user display name. + * + * @throws Exception If $user_id argument is invalid. + */ + public function get_user_display_name($user_id) + { + if ( ! is_numeric($user_id)) + { + throw new Exception ('Invalid argument given: ' . $user_id); + } + + $user = $this->db->get_where('users', ['id' => $user_id])->row_array(); + + return $user['first_name'] . ' ' . $user['last_name']; + } + + /** + * If the given arguments correspond to an existing user record, generate a new + * password and send it with an email. + * + * @param string $username User's username. + * @param string $email User's email. + * + * @return string|bool Returns the new password on success or FALSE on failure. + */ + public function regenerate_password($username, $email) + { + $this->load->helper('general'); + $this->load->helper('string'); + + $result = $this->db + ->select('users.id') + ->from('users') + ->join('user_settings', 'user_settings.id_users = users.id', 'inner') + ->where('users.email', $email) + ->where('user_settings.username', $username) + ->get(); + + if ($result->num_rows() == 0) + { + return FALSE; + } + + $user_id = $result->row()->id; + + // Create a new password and send it with an email to the given email address. + $new_password = random_string('alnum', 12); + $salt = $this->db->get_where('user_settings', ['id_users' => $user_id])->row()->salt; + $hash_password = hash_password($salt, $new_password); + $this->db->update('user_settings', ['password' => $hash_password], ['id_users' => $user_id]); + + return $new_password; + } + + /** + * Get the timezone of a user. + * + * @param int $id Database ID of the user. + * + * @return string|null + */ + public function get_user_timezone($id) + { + $row = $this->db->get_where('users', ['id' => $id])->row_array(); + + return $row ? $row['timezone'] : NULL; + } +} diff --git a/src/assets/js/index.html b/application/models/index.html similarity index 100% rename from src/assets/js/index.html rename to application/models/index.html diff --git a/application/views/appointments/book.php b/application/views/appointments/book.php new file mode 100755 index 00000000..adc8912c --- /dev/null +++ b/application/views/appointments/book.php @@ -0,0 +1,471 @@ + + + + + + + + + <?= lang('page_title') . ' ' . $company_name ?> + + + + + + + + + + + + + + + +
+
+
+ + + + + + +
+
+ +
+
+
+ + + + + + +
+
+
+
+
+ +
+
+ +
+
+ + + +
+

+ + + + +
+ + + + + +
+
+

+ +
+
+
+ + + +
+ +
+ + + +
+ +
+
+
+
+ +
+   + + +
+
+ + + + + + + + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/application/views/appointments/book_success.php b/application/views/appointments/book_success.php new file mode 100755 index 00000000..590fde1d --- /dev/null +++ b/application/views/appointments/book_success.php @@ -0,0 +1,98 @@ + + + + + + + + <?= lang('appointment_registered') . ' - ' . $company_name ?> + + + + + + + + + + +
+
+
+
+ +
+ +
+

+ +

+ +

+ +

+ + + +

+ + + + + + + + + + + +
+

+ + + + +
+ +
+ +
+ + Powered by + Easy!Appointments + +
+
+
+
+ + + + + + + + + + + + + + + diff --git a/application/views/appointments/cookie_notice_modal.php b/application/views/appointments/cookie_notice_modal.php new file mode 100644 index 00000000..61ee08ee --- /dev/null +++ b/application/views/appointments/cookie_notice_modal.php @@ -0,0 +1,18 @@ + diff --git a/application/views/appointments/index.html b/application/views/appointments/index.html new file mode 100644 index 00000000..5fcd693f --- /dev/null +++ b/application/views/appointments/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/application/views/appointments/message.php b/application/views/appointments/message.php new file mode 100644 index 00000000..819b0a17 --- /dev/null +++ b/application/views/appointments/message.php @@ -0,0 +1,62 @@ + + + + + + + + + <?= $message_title ?> | Easy!Appointments + + + + + + + + + + + + + + + + + +
+
+
+
+ warning +
+ +
+

+

+ + +
+

+ + + +
+ +
+ +
+ + Powered by + Easy!Appointments + +
+
+
+
+ + + + diff --git a/application/views/appointments/privacy_policy_modal.php b/application/views/appointments/privacy_policy_modal.php new file mode 100644 index 00000000..246d4734 --- /dev/null +++ b/application/views/appointments/privacy_policy_modal.php @@ -0,0 +1,18 @@ + diff --git a/application/views/appointments/terms_and_conditions_modal.php b/application/views/appointments/terms_and_conditions_modal.php new file mode 100644 index 00000000..0522e88b --- /dev/null +++ b/application/views/appointments/terms_and_conditions_modal.php @@ -0,0 +1,18 @@ + diff --git a/application/views/backend/calendar.php b/application/views/backend/calendar.php new file mode 100755 index 00000000..6e886e11 --- /dev/null +++ b/application/views/backend/calendar.php @@ -0,0 +1,493 @@ + + + + + + + + + + + + + + + +
+
+
+
+ +
+
+ +
+ + + + + + + +
+ + + + + +
+ + + + + + + + + + + + + + + +
+
+ +
+
+ + + + + + + + + + + + + + + + + + diff --git a/application/views/backend/customers.php b/application/views/backend/customers.php new file mode 100755 index 00000000..c5996eab --- /dev/null +++ b/application/views/backend/customers.php @@ -0,0 +1,184 @@ + + + + + +
+
+
+
+
+ + +
+
+ + +
+
+
+
+ +

+
+
+ +
+
+
+ + + + + + + + + + + +
+ + +
+ + + +
+
+

+ + + +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+

+
+
+
+
+
+
+
diff --git a/application/views/backend/footer.php b/application/views/backend/footer.php new file mode 100644 index 00000000..19ff9b10 --- /dev/null +++ b/application/views/backend/footer.php @@ -0,0 +1,38 @@ + + + + + + + diff --git a/application/views/backend/header.php b/application/views/backend/header.php new file mode 100755 index 00000000..42f731a8 --- /dev/null +++ b/application/views/backend/header.php @@ -0,0 +1,119 @@ + + + + + + + <?= isset($page_title) ? $page_title : lang('backend_section') ?> | Easy!Appointments + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/application/views/backend/index.html b/application/views/backend/index.html new file mode 100644 index 00000000..5fcd693f --- /dev/null +++ b/application/views/backend/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/application/views/backend/services.php b/application/views/backend/services.php new file mode 100755 index 00000000..741b30c5 --- /dev/null +++ b/application/views/backend/services.php @@ -0,0 +1,264 @@ + + + + + +
+ + +
+ + + +
+
+
+
+
+ + +
+
+ + +
+
+
+
+ +

+
+
+ +
+
+
+ + + +
+ + +
+ +

+ + + + + +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+
+ + + +
+
+
+
+
+ + +
+
+ + +
+
+
+
+ +

+
+
+ +
+
+
+ + + +
+ + +
+ +

+ + + + + +
+ + +
+ +
+ + +
+
+
+
+
+
diff --git a/application/views/backend/settings.php b/application/views/backend/settings.php new file mode 100755 index 00000000..56b209c3 --- /dev/null +++ b/application/views/backend/settings.php @@ -0,0 +1,555 @@ + + + + + + + + +
+ + +
+ + + + +
+
+
+ + + + + + + +
+
+
+ + + + + +
+ +
+ + + + + +
+ +
+ + + + + +
+
+ + + + + +
+
+ + + + + +
+
+ + + + + +
+
+
+
+ + + + + +
+
+ + + + + +
+ +
+
+ + +
+ + + +
+
+
+ + +
+ + + +
+
+
+ + +
+ + + +
+
+
+ + +
+ + + +
+
+
+
+
+
+ + + + +
+
+
+ + + + + + + +
+
+

+ + + + + + + + + + + + + +
+ +
+ +
+ +
+ +

+
+ + +

+ +

+
+
+
+

+ + + + + +
+ +
+ +
+ + + + + + + + + + + +
+
+
+
+
+
+ + + + + + + + + +
+
+
+
+ + + + + + + + + +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+ + +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+
+
+ + + +
+

Easy!Appointments

+ +

+ +

+ +
+ + + + - + +
+ +

+

+ + +

+ + + + + | + + + + | + + + + | + + Blog + + | + + Facebook + + | + + Twitter + +

+ +

+ +

+ + http://www.gnu.org/copyleft/gpl.html +

+
+ +
+
diff --git a/application/views/backend/users.php b/application/views/backend/users.php new file mode 100755 index 00000000..0bf0b5e4 --- /dev/null +++ b/application/views/backend/users.php @@ -0,0 +1,772 @@ + + + + + + + + + + +
+ + + + +
+ + + +
+
+
+
+
+ + + +
+ + +
+
+
+
+ +

+
+
+ +
+
+
+ + + +
+ + +
+ + + + + + + +
+
+

+ + + +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ + +
+ +
+ +

+
+
+
+
+ +
+

+ + + + + + + + + + +
+ +
+ +

+ +

+ +

+ +
+ +
+ +
+ + + + + + + + + + + +
+ +
+ +

+ +

+ +

+ +
+ +
+ +
+ + + + + + + + + + + +
+ + +
+
+
+
+
+ + + +
+
+
+
+
+ + + +
+ + +
+
+
+
+ +

+ +
+
+ +
+
+
+ + + +
+ + +
+ +

+ + + + + +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ + +
+ +
+ +

+
+
+
+
+
+
+ + + +
+
+
+
+
+ + + +
+ + +
+
+
+
+ +

+ +
+
+ +
+
+
+ + + +
+ + +
+ +

+ + + + + +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ + +
+
+
+
+
+
+
+
diff --git a/application/views/backend/working_plan_exceptions_modal.php b/application/views/backend/working_plan_exceptions_modal.php new file mode 100644 index 00000000..d23c6b64 --- /dev/null +++ b/application/views/backend/working_plan_exceptions_modal.php @@ -0,0 +1,58 @@ + diff --git a/application/views/emails/appointment_details.php b/application/views/emails/appointment_details.php new file mode 100644 index 00000000..6b04918c --- /dev/null +++ b/application/views/emails/appointment_details.php @@ -0,0 +1,74 @@ + + + <?= lang('appointment_details_title') ?> | Easy!Appointments + + +
+ + +
+

+

+ +

+ + + + + + + + + + + + + + + + + + + + + +
+ +

+ + + + + + + + + + + + + + + + + +
+ +

+ +
+ + +
+ + diff --git a/application/views/emails/delete_appointment.php b/application/views/emails/delete_appointment.php new file mode 100644 index 00000000..4b057bf6 --- /dev/null +++ b/application/views/emails/delete_appointment.php @@ -0,0 +1,74 @@ + + + <?= lang('appointment_cancelled_title') ?> | Easy!Appointments + + +
+ + +
+

+

+ +

+ + + + + + + + + + + + + + + + + + + + + +
+ +

+ + + + + + + + + + + + + + + + + +
+ +

+

+
+ + +
+ + diff --git a/application/views/emails/index.html b/application/views/emails/index.html new file mode 100644 index 00000000..221ac80d --- /dev/null +++ b/application/views/emails/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/application/views/emails/new_password.php b/application/views/emails/new_password.php new file mode 100644 index 00000000..157d52dc --- /dev/null +++ b/application/views/emails/new_password.php @@ -0,0 +1,27 @@ + + + New Password | Easy!Appointments + + +
+ + +
+

+

+
+ + +
+ + diff --git a/src/application/views/errors/cli/error_404.php b/application/views/errors/cli/error_404.php similarity index 100% rename from src/application/views/errors/cli/error_404.php rename to application/views/errors/cli/error_404.php diff --git a/src/application/views/errors/cli/error_db.php b/application/views/errors/cli/error_db.php similarity index 100% rename from src/application/views/errors/cli/error_db.php rename to application/views/errors/cli/error_db.php diff --git a/src/application/views/errors/cli/error_exception.php b/application/views/errors/cli/error_exception.php similarity index 100% rename from src/application/views/errors/cli/error_exception.php rename to application/views/errors/cli/error_exception.php diff --git a/src/application/views/errors/cli/error_general.php b/application/views/errors/cli/error_general.php similarity index 100% rename from src/application/views/errors/cli/error_general.php rename to application/views/errors/cli/error_general.php diff --git a/src/application/views/errors/cli/error_php.php b/application/views/errors/cli/error_php.php similarity index 100% rename from src/application/views/errors/cli/error_php.php rename to application/views/errors/cli/error_php.php diff --git a/application/views/errors/cli/index.html b/application/views/errors/cli/index.html new file mode 100644 index 00000000..bcb7cae3 --- /dev/null +++ b/application/views/errors/cli/index.html @@ -0,0 +1,11 @@ + + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/src/application/views/errors/html/error_404.php b/application/views/errors/html/error_404.php similarity index 100% rename from src/application/views/errors/html/error_404.php rename to application/views/errors/html/error_404.php diff --git a/src/application/views/errors/html/error_db.php b/application/views/errors/html/error_db.php similarity index 100% rename from src/application/views/errors/html/error_db.php rename to application/views/errors/html/error_db.php diff --git a/src/application/views/errors/html/error_exception.php b/application/views/errors/html/error_exception.php similarity index 100% rename from src/application/views/errors/html/error_exception.php rename to application/views/errors/html/error_exception.php diff --git a/src/application/views/errors/html/error_general.php b/application/views/errors/html/error_general.php similarity index 100% rename from src/application/views/errors/html/error_general.php rename to application/views/errors/html/error_general.php diff --git a/src/application/views/errors/html/error_php.php b/application/views/errors/html/error_php.php similarity index 100% rename from src/application/views/errors/html/error_php.php rename to application/views/errors/html/error_php.php diff --git a/application/views/errors/html/index.html b/application/views/errors/html/index.html new file mode 100644 index 00000000..5fcd693f --- /dev/null +++ b/application/views/errors/html/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/application/views/errors/index.html b/application/views/errors/index.html new file mode 100644 index 00000000..5fcd693f --- /dev/null +++ b/application/views/errors/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/application/views/general/error404.php b/application/views/general/error404.php new file mode 100644 index 00000000..9d442691 --- /dev/null +++ b/application/views/general/error404.php @@ -0,0 +1,57 @@ + + + + + + + + + <?= lang('page_not_found') ?> | Easy!Appointments + + + + + + + + + + + + + + + + + + +
+

+

+ +

+ + + + + + + + + + + +
+ + Powered by + Easy!Appointments + +
+
+ + + + diff --git a/application/views/general/index.html b/application/views/general/index.html new file mode 100644 index 00000000..5fcd693f --- /dev/null +++ b/application/views/general/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/application/views/general/installation.php b/application/views/general/installation.php new file mode 100755 index 00000000..bc311d4c --- /dev/null +++ b/application/views/general/installation.php @@ -0,0 +1,153 @@ + + + + + + Installation | Easy!Appointments + + + + + + + + +
+ +
+ +
+ + Easy!Appointments Installation Banner + +
+ +
+
+

Welcome to the Easy!Appointments installation page.

+

+ This page will help you set the main settings of your Easy!Appointments installation. + You will be able to edit these settings and many more in the backend session of your + system. Remember to use the + url to connect to the backend section of Easy!Appointments. + + If you face any problems during the usage of Easy!Appointments you can always check the + Documentation + and Support Group for getting help. You + may also submit new issues on + GitHub Issues + in order to help our development process. +

+
+ +
+ +
+
+

Administrator

+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+

Company

+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ +
+ +

+ You will be able to set your business logic in the backend settings page + after the installation is complete. +
+ Press the following button to complete the installation process. +

+ +
+ +

+

License

+ Easy!Appointments is licensed under the GPLv3 license. + By using the code of Easy!Appointments in any way
you agree with the terms described in the + following url: + http://www.gnu.org/copyleft/gpl.html +

+ +
+ + +
+ + + + + + + + + + + + + + diff --git a/application/views/general/update.php b/application/views/general/update.php new file mode 100644 index 00000000..34f88b1b --- /dev/null +++ b/application/views/general/update.php @@ -0,0 +1,59 @@ + + + + + + Update | Easy!Appointments + + + + + + + + +
+
+ + Easy!Appointments Installation Banner + +
+
+ +
+ +

+ The database was updated successfully! +

+ +

+ You can now use the latest Easy!Appointments version. +

+ +

+ There was an error during the update process ... +

+ +

+ Please restore your database backup. +

+ +
+ Error Message: +
+ + +
+ + + + +
+
+ + + + diff --git a/application/views/index.html b/application/views/index.html new file mode 100644 index 00000000..5fcd693f --- /dev/null +++ b/application/views/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/application/views/partial/index.html b/application/views/partial/index.html new file mode 100644 index 00000000..5fcd693f --- /dev/null +++ b/application/views/partial/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/application/views/partial/timezone_dropdown.php b/application/views/partial/timezone_dropdown.php new file mode 100644 index 00000000..77a34ec2 --- /dev/null +++ b/application/views/partial/timezone_dropdown.php @@ -0,0 +1,9 @@ + diff --git a/application/views/user/forgot_password.php b/application/views/user/forgot_password.php new file mode 100644 index 00000000..b8f31947 --- /dev/null +++ b/application/views/user/forgot_password.php @@ -0,0 +1,74 @@ + + + + + + + + + <?= lang('forgot_your_password') ?> | Easy!Appointments + + + + + + + + + + + + + + + + + +
+

+

+
+
+
+
+ + +
+
+ + +
+ +
+ + + + +
+ +
+ + Powered by + Easy!Appointments + +
+
+ + + + + + diff --git a/application/views/user/index.html b/application/views/user/index.html new file mode 100644 index 00000000..5fcd693f --- /dev/null +++ b/application/views/user/index.html @@ -0,0 +1,10 @@ + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/application/views/user/login.php b/application/views/user/login.php new file mode 100644 index 00000000..4cffdddc --- /dev/null +++ b/application/views/user/login.php @@ -0,0 +1,89 @@ + + + + + + + + <?= lang('login') ?> | Easy!Appointments + + + + + + + + + + + + + + + + + +
+

+

+
+
+
+
+ + +
+
+ + +
+ +
+ +
+ + + + | + + + + +
+ + Powered by + Easy!Appointments + +
+
+
+ + + + + + + diff --git a/application/views/user/logout.php b/application/views/user/logout.php new file mode 100644 index 00000000..d0e39dc9 --- /dev/null +++ b/application/views/user/logout.php @@ -0,0 +1,53 @@ + + + + + + + + + <?= lang('log_out') ?> | Easy!Appointments + + + + + + + + + + + + + + + +
+

+

+ +

+ +
+ + + + + + + + + + + +
+ + Powered by + Easy!Appointments + +
+
+ + diff --git a/application/views/user/no_privileges.php b/application/views/user/no_privileges.php new file mode 100644 index 00000000..035462d5 --- /dev/null +++ b/application/views/user/no_privileges.php @@ -0,0 +1,43 @@ + + + + + + + + + <?= lang('no_privileges') ?> | Easy!Appointments + + + + + + + + + + + + +
+

+

+ +

+ +
+ + + + + + +
+ + Powered by + Easy!Appointments + +
+
+ + diff --git a/assets/css/backend.css b/assets/css/backend.css new file mode 100644 index 00000000..d024de10 --- /dev/null +++ b/assets/css/backend.css @@ -0,0 +1,874 @@ +/* ---------------------------------------------------------------------------- + * Easy!Appointments - Open Source Web Scheduler + * + * @package EasyAppointments + * @author A.Tselegidis + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +/** + * BACKEND CSS FILE FOR EASY!APPOINTMENTS + */ + +root { + display: block; +} + +/* BACKEND GENERAL ELEMENTS + -------------------------------------------------------------------- */ + +#header { + background-color: #429a82; + box-shadow: none; + border-radius: 0; + padding: 0; +} + +#header #header-logo { + padding: 5px; +} + +#header #header-logo img { + float: left; + width: 45px; + height: 45px; + margin-right: 10px; +} + +#header #header-logo span { + float: left; + font-size: 14px; + font-weight: bold; + color: white; + margin-top: 12px; +} + +#header .navbar-toggler { + margin-right: 5px; +} + +#header .nav-link { + color: white; + padding: 20px 15px; + font-weight: lighter; +} + +#header #header-menu .nav-item { + min-width: 100px; + text-align: center; +} + +#header #header-menu .nav-item:hover { + background: #3a8873; +} + +#header #header-menu .nav-item.active { + background: #2e6a5b; +} + +#footer { + background-color: #F7F7F7; + border-top: 1px solid #DDD; + font-size: 11px; + overflow: auto; +} + +#footer #footer-content { + padding: 10px 15px; + display: inline-block; + float: left; + line-height: 2; +} + +#footer #footer-user-display-name { + display: inline-block; + padding: 10px 15px; + font-weight: bold; +} + +#notification { + margin: 15px; +} + +#notification strong { + margin-right: 15px; +} + +#notification .alert button { + margin-right: 15px; +} + +#notification .alert { + margin-bottom: 0; + background-color: #f5e8a8; + color: #9E9980; + box-shadow: 1px 1px 1px #a0a0a0; + padding: 15px; + position: fixed; + z-index: 200; + right: 15px; + bottom: 15px; + min-width: 300px; + max-width: 750px; +} + +#notification .close { + color: #9E9980; + font-size: 25px; + line-height: 0.8; + margin-right: 0 !important; +} + +#loading { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 999999; + background: rgba(255, 255, 255, 0.75); +} + +#loading img { + margin: auto; + display: block; + max-width: 100%; +} + +.modal-message { + margin-bottom: 10px; +} + +body .modal .modal-title { + color: white; +} + +body .modal-header { + padding: 20px 15px; + background: #429a82; +} + +body .modal-header h3 { + color: #FFF; + font-size: 20px; + font-weight: lighter; +} + +body .modal-header .close { + color: #12482a; +} + +body .modal-content { + border: none; +} + +/* Full screen modal */ +body .modal.full-screen .modal-dialog { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} + +body .modal.full-screen .modal-content { + height: 100%; + border: none; + box-shadow: none; + overflow-y: auto; +} + +body .modal.full-screen .wrapper { + min-height: 100%; + margin-bottom: -67px; /* modal-footer height */ +} + +body .modal.full-screen .modal-footer { + background-color: #f5f5f5; + width: 100%; + height: 67px; +} + +body .modal.full-screen .modal-push { + height: 67px; +} + +body .jspDrag { + background: #D3D3D3; +} + +body .jspTrack { + background: #EBEBEB; +} + +body legend { + color: #666; +} + +@media (min-width: 768px) { + #footer #footer-user-display-name { + float: right; + text-align: right; + } +} + +/* BACKEND COMPONENTS + -------------------------------------------------------------------- */ + +.backend-page { + padding-top: 15px; + padding-bottom: 15px; +} + +.backend-page .filter-records { + max-width: 350px; + margin-bottom: 20px; +} + +.backend-page .filter-records form .input-group-addon { + padding-top: 0; + padding-right: 0; + border-top: none; +} + +.backend-page .filter-records form .key { + margin-right: 15px; + float: left; +} + +.backend-page .filter-records .results { + overflow-y: auto; + max-height: 650px; + outline: none; +} + +.backend-page .filter-records .results .entry { + padding: 10px 7px; +} + +.backend-page .filter-records .results .entry:hover:not(.selected) { + background-color: #F3F3F3; + cursor: pointer; +} + +.backend-page .filter-records .results .entry.selected { + background-color: #F4F4F4; + border-right: 5px solid #429a82; +} + +.backend-page .filter-records .results hr { + margin: 5px 0; +} + +.record-details { + max-width: 800px; + margin-bottom: 20px; +} + +.record-details input:read-only, +.record-details select:disabled, +.record-details textarea:read-only { + opacity: 0.85; + box-shadow: none; +} + +.backend-page .nav-pills li { + width: 100%; + text-align: center; + margin: 5px; +} + +@media (min-width: 768px) { + .backend-page .nav-pills li { + width: auto; + } +} + + +/* BACKEND CALENDAR PAGE + -------------------------------------------------------------------- */ + +#calendar-page { + padding-top: 0; + padding-bottom: 0; +} + +#calendar-page #calendar-toolbar { + margin-bottom: 15px; + color: white; + background: #353535; + padding: 15px 0; +} + +#calendar-page #calendar-filter .form-group { + margin-bottom: 0; +} + +#calendar-page #calendar-filter .form-control { + background-color: #FFF; + padding: 0 10px; + background-position-x: 95%; + margin-bottom: 10px; +} + +#calendar-page #calendar-filter select:disabled { + background: white; + cursor: auto; +} + +#calendar-page #calendar-actions .btn { + width: 100%; + margin-bottom: 10px; +} + +#calendar-page #calendar-actions > .btn-group { + width: 100%; +} + +#calendar-page #calendar-actions > .btn-group .btn { + width: auto; +} + +#calendar-page #calendar-actions > .btn-group .btn:not(.dropdown-toggle) { + text-align: right; +} + +#calendar-page #calendar-actions > .btn-group .btn.dropdown-toggle { + text-align: left; +} + +#calendar-page #calendar { + margin-bottom: 15px; + font-size: 15.2px; +} + +#calendar-page #calendar .fc-toolbar .fc-left, +#calendar-page #calendar .fc-toolbar .fc-right { + float: none; + overflow: auto; + margin-bottom: 10px; +} + +#calendar-page #calendar .fc-toolbar.fc-header-toolbar h2 { + font-size: 22px; + display: block +} + +#calendar-page #calendar .fc-toolbar.fc-header-toolbar .fc-center { + margin-top: 0; +} + +#calendar-page #calendar .fc-unavailable { + background-image: url('../img/unavailable.jpg'); + font-size: 14px; + border-radius: 0; + font-weight: bold; + color: #333; + text-shadow: 0 1px 0 #E6E6E6; + opacity: 0.7; +} + +#calendar-page #calendar .fc-event-title small { + font-weight: normal; + font-size: 12px; +} + +#calendar-page #calendar .fc-time { + font-size: 10px; +} + +#calendar-page #calendar .fc-break { + background-image: url('../img/break.jpg'); +} + +#calendar-page #calendar .fc-custom { + background-image: url('../img/custom.jpg'); +} + +#calendar-page .fc-header { + margin-bottom: 10px; +} + +#calendar .fc-time-grid-event.fc-short .fc-title { + font-size: .7em; +} + +#calendar .fc-header-title h2 { + font-size: 16px; + margin: 0; + line-height: 26px; +} + +#calendar .fc-header .fc-button { + margin-bottom: 8px; + background-image: none !important; +} + +#calendar .fc-agenda-allday .fc-day-content { + min-height: 19px; +} + +#calendar .fc-agenda-divider-inner { + height: 3px; +} + +#calendar table thead .fc-first { + background: #F5F5F5; +} + +#calendar table thead .fc-first th { + vertical-align: middle; + padding: 2px 0; + color: #555; +} + +#calendar .fc-event { + border: 1px solid #4790CA; + background-color: #4790CA; +} + +#existing-customers-list { + height: 110px; + overflow-y: auto; + margin-bottom: 8px; + font-size: 12px; + line-height: 22px; +} + +#existing-customers-list div { + display: inline-block; + width: 250px; + margin: 0 7px 7px 0; + padding: 5px; + border-radius: 3px; +} + +#existing-customers-list div:hover { + background: #429a82; + font-weight: bold; + color: #FFF; + cursor: pointer; +} + +#filter-existing-customers { + display: inline-block; + height: 14px; + min-height: 24px; + font-size: 12px; +} + +#appointment-notes, +#customer-notes { + height: 37px; /* Align with location field */ +} + +body .form-horizontal .control-label { + width: 135px; +} + +body .form-horizontal .controls { + margin-left: 158px; +} + +#calendar .calendar-header { + padding-bottom: 15px; +} + +#calendar .calendar-header input { + width: 120px; + vertical-align: middle; +} + +#calendar .calendar-header select { + min-width: 300px; +} + +#calendar .calendar-header label { + margin: 10px 0; + vertical-align: middle; + display: block; +} + +#calendar .calendar-header .select2-container--default .select2-selection--multiple { + height: 38px; +} + +#calendar .select2-container--default.select2-container--focus .select2-selection--multiple { + border-color: #80bdff; + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(0,123,255,.25); +} + +#calendar .select2-container--default .select2-selection--multiple .select2-selection__choice { + background-color: #f8f9fa; + border: 1px solid #ced4da; +} + +#calendar .calendar-view { + overflow-x: auto; +} + +#calendar .calendar-view > div { + width: 100%; + min-width: 1000%; + overflow: auto; +} + +#calendar .calendar-view .date-column { + overflow: auto; + float: left; + margin-right: 20px; +} + +#calendar .fc-unavailable { + background: #eaeaea url('../img/unavailable.jpg'); +} + +#calendar .calendar-view .date-column .provider-column { + overflow: auto; + float: left; + margin-right: 10px; + width: 500px; +} + +#calendar .calendar-view .date-column .provider-column table thead { + background-color: #FFF; +} + +#calendar .calendar-view .date-column .provider-column .event { + font-size: 10px; + border-radius: 3px; + padding: 2px 3px; + cursor: pointer; + margin: 1px 25px 1px 1px; +} + +#calendar .calendar-view .date-column .provider-column .event.appointment { + background: #4790CA; + color: #fff; +} + +#calendar .calendar-view .date-column .provider-column .event.unavailability { + background: #409482; + color: #fff; + +} + +@media (min-width: 768px) { + #calendar-page #calendar-actions { + text-align: right; + } + + #calendar-page #calendar-filter .form-group .form-control { + max-width: 300px; + margin-bottom: 0; + } + + #calendar-page #calendar-actions .btn { + width: auto; + margin-bottom: 0; + } + + #calendar-page #calendar-actions > .btn-group { + width: auto; + } + + #calendar-page #calendar-actions > .btn-group .btn { + width: auto; + } + + #calendar-page #calendar-actions > .btn-group .btn:not(.dropdown-toggle) { + text-align: center; + } + + #calendar-page #calendar-actions > .btn-group .btn.dropdown-toggle { + text-align: center; + } + + #calendar-page #calendar .fc-toolbar .fc-left { + float: left; + margin-bottom: 0; + } + + #calendar-page #calendar .fc-toolbar .fc-right { + float: right; + margin-bottom: 0; + } + + #calendar-page #calendar .fc-toolbar.fc-header-toolbar h2 { + font-size: 22px; + display: inline-block; + } + + #calendar .calendar-header label { + display: inline-block; + margin: 0 10px; + } +} + + +/* BACKEND CUSTOMERS PAGE + -------------------------------------------------------------------- */ + +#customers-page #customer-appointments { + min-height: 400px; + max-height: 800px; + max-width: 330px; + width: 100%; + margin-bottom: 20px; + overflow-y: auto; + outline: none; + padding: 15px; +} + +#customers-page #customer-appointments .appointment-row { + padding: 7px; + border-bottom: 1px solid #E2E2E2; + border-right: none; +} + +#customers-page #customer-appointments .appointment-row:last-child { + border-bottom: none; +} + + +/* BACKEND SERVICES PAGE + -------------------------------------------------------------------- */ + +#services-page h2 { + color: #525252; +} + +#services-page .nav { + background-color: #F4F4F4; + margin-bottom: 15px; +} + +#services-page .nav li { + cursor: pointer; +} + +#services-page .record-details .ui-state-disabled { + opacity: 1; +} + +#services-page #service-duration { + margin: 0; +} + +#services-page .record-details h3 a { + font-size: 24px; + margin-left: 10px; +} + +/* BACKEND USERS PAGE + -------------------------------------------------------------------- */ + +#users-page h2 { + color: #525252; +} + +#users-page .nav { + background-color: #F4F4F4; + margin-bottom: 15px; +} + +#users-page .nav li { + cursor: pointer; +} + +#users-page #secretary-notifications.active, +#users-page #provider-notifications.active, +#users-page #admin-notifications.active { + background: #B6DCFF; + box-shadow: none; +} + +#users-page #secretary-providers, +#users-page #provider-services { + max-width: 315px; + width: 100%; + height: 387px; + overflow-y: auto; + margin-bottom: 20px; +} + +#users-page #providers .switch-view { + overflow: auto; + background: none; + padding: 0; + margin: 0; +} + +#users-page #providers .switch-view .nav-item { + margin: 0; +} + +#users-page #providers .working-plan-view .work-start, +#users-page #providers .working-plan-view .work-end { + max-width: 88px; +} + +#users-page .btn-toolbar { + margin-top: 0; + margin-bottom: 15px; +} + +#users-page #providers .form-message { + clear: both; +} + +#users-page #providers .breaks .btn { + margin-right: 5px; + padding: 4px 7px; +} + +#users-page #providers .working-plan-exceptions .btn { + margin-right: 5px; + padding: 4px 7px; +} + +@-moz-document url-prefix() { + .breaks .break-day select { + height: 36px; + } + + .working-plan-exceptions .working-plan-exception select { + height: 36px; + } +} + +#users-page .working-plan .checkbox, +#users-page .working-plan input[type="text"], +#users-page .working-plan button { + margin: 2px 0; +} + +#users-page .working-plan td input[type="text"] { + width: 55px; +} + +#users-page .editable form, +#users-page .editable select, +#users-page .editable input { + margin: 0; +} + +#users-page #providers .record-details h3 a { + font-size: 24px; + margin-left: 10px; +} + +#users-page #providers .record-details #provider-services .checkbox a { + margin-left: 5px; +} + +/* BACKEND SETTINGS PAGE + -------------------------------------------------------------------- */ + +#settings-page h2 { + color: #525252; +} + +#settings-page .nav { + background-color: #F4F4F4; + margin-bottom: 15px; +} + +#business-logic .working-plan .checkbox, +#business-logic .working-plan input[type="text"], +#business-logic .working-plan button { + margin: 2px 0; +} + +#business-logic .working-plan td input[type="text"] { + max-width: 88px; +} + +#business-logic .working-plan .work-start, +#business-logic .working-plan .work-end { + max-width: 88px; +} + +#business-logic .working-plan label.checkbox { + margin-top: 5px; + margin-bottom: 0; +} + +#business-logic .breaks .btn { + margin-right: 5px; + padding: 4px 7px; +} + +#business-logic .breaks input { + margin-bottom: 0; +} + +#business-logic .breaks .editable form { + margin: 0; +} + +#business-logic .breaks .editable select, +#business-logic .breaks .editable input { + margin: 0; + cursor: pointer; +} + +#business-logic #book-advance-timeout { + width: 100px; +} + +#settings-page #user-notifications, +#settings-page #customer-notifications, +#settings-page #display-any-provider, +#settings-page #require-phone-number, +#settings-page #require-captcha { + outline: none; +} + +#settings-page #user-notifications.active, +#settings-page #customer-notifications.active, +#settings-page #display-any-provider.active, +#settings-page #require-phone-number.active, +#settings-page #require-captcha.active { + background: #B6DCFF; +} + +#settings-page #general fieldset .wrapper { + max-width: 1024px; +} + +#settings-page .working-plan-wrapper { + max-width: 600px; +} + +#settings-page .breaks-wrapper { + max-width: 500px; +} + +#settings-page .personal-info-wrapper { + max-width: 400px; + margin-bottom: 20px; +} + +#settings-page .miscellaneous-wrapper { + max-width: 400px; + margin-bottom: 20px; +} + +#settings-page #about { + max-width: 720px; +} + +#settings-page #about .current-version { + padding: 15px; + background: #F4F4F4; + font-size: 12px; + color: #444; +} + +#settings-page #update-ea { + margin-left: 12px; +} diff --git a/assets/css/error404.css b/assets/css/error404.css new file mode 100644 index 00000000..4393da36 --- /dev/null +++ b/assets/css/error404.css @@ -0,0 +1,36 @@ +body { + width: 100vw; + height: 100vh; + display: table-cell; + vertical-align: middle; + background-color: #f5f8fa; +} + +#message-frame { + width: 630px; + margin: auto; + background: #FFF; + border: 1px solid #DDDADA; + padding: 70px; +} + +.btn { + margin-right: 10px; +} + +@media(max-width: 640px) { + body { + display: block; + } + + #message-frame { + width: 100%; + height: 100%; + padding: 20px; + } + + .btn { + width: 100%; + margin-bottom: 20px; + } +} diff --git a/assets/css/forgot_password.css b/assets/css/forgot_password.css new file mode 100644 index 00000000..03282d95 --- /dev/null +++ b/assets/css/forgot_password.css @@ -0,0 +1,26 @@ +body { + width: 100vw; + height: 100vh; + display: table-cell; + vertical-align: middle; + background-color: #f5f8fa; +} + +#forgot-password-frame { + width: 630px; + margin: auto; + background: #FFF; + border: 1px solid #DDDADA; + padding: 70px; +} + +.user-login { + margin-left: 20px; +} + +@media(max-width: 640px) { + #forgot-password-frame { + width: 100%; + padding: 20px; + } +} diff --git a/assets/css/frontend.css b/assets/css/frontend.css new file mode 100644 index 00000000..49c62c0a --- /dev/null +++ b/assets/css/frontend.css @@ -0,0 +1,425 @@ +/* ---------------------------------------------------------------------------- + * Easy!Appointments - Open Source Web Scheduler + * + * @package EasyAppointments + * @author A.Tselegidis + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +root { + display: block; +} + +html, +body { + height: 100%; +} + +body { + background-color: #f5f8fa; +} + +#main { + min-height: 100%; +} + +/* BOOK APPOINTMENT WIZARD + ------------------------------------------------------------------------------ */ + +#book-appointment-wizard { + background: #FFF; + min-height: 480px; + padding: 0; + margin: auto; +} + +#book-appointment-wizard #header { + overflow: auto; + height: auto; + padding: 20px 15px; + background: #429a82; +} + +#book-appointment-wizard #company-name { + float: none; + display: block; + text-align: center; + font-size: 24px; + font-weight: lighter; + color: #FFF; + margin: 20px 0; +} + +#book-appointment-wizard #steps { + float: none; + display: block; + overflow: auto; + margin: 15px auto; + width: 190px; +} + +#book-appointment-wizard #book-appointment-form #book-appointment-submit { + width: 100%; + margin-right: 0; +} + +#book-appointment-wizard #form-message { + text-align: center; + margin-bottom: 30px; +} + +#book-appointment-wizard .wizard-frame { + height: auto; + padding: 15px; +} + +#book-appointment-wizard .wizard-frame .frame-container { + height: auto; + min-height: 500px; + padding: 15px 0; +} + +#book-appointment-wizard .frame-container .frame-title { + font-weight: lighter; + text-align: center; + margin-bottom: 30px; + color: #666; +} + +#book-appointment-wizard .frame-container .frame-content { + float: none; +} + +#book-appointment-wizard .wizard-frame .command-buttons { + float: none; + margin: 15px auto; + text-align: center; +} + +#book-appointment-wizard .wizard-frame .command-buttons .btn { + min-width: 120px; + margin-right: 10px; +} + +#book-appointment-wizard .wizard-frame .command-buttons .btn:last-child { + margin-right: 0; +} + +#book-appointment-wizard .wizard-frame #select-date { + max-width: 288px; + margin: auto; + padding: 15px 0; +} + +#book-appointment-wizard .wizard-frame #select-date > .ui-datepicker { + margin: auto; +} + +#book-appointment-wizard .wizard-frame #select-time { + max-width: 288px; + margin: auto; + padding: 15px 0; +} + +#book-appointment-wizard .book-step { + display: inline-block; + height: 35px; + width: 35px; + float: left; + background: #225d4d; + padding: 8px; + margin-right: 12px; + margin-top: 6px; + border-radius: .25rem; + transition: all .3s linear; +} + +#book-appointment-wizard .book-step:last-child { + margin-right: 0; +} + +#book-appointment-wizard .book-step strong { + font-size: 12px; + display: block; + text-align: center; + color: #0bb98d; + transition: all .3s linear; +} + +#book-appointment-wizard .active-step { + display: inline-block; + height: 45px; + width: 45px; + float: left; + background: #FFF; + padding: 7px; + margin-right: 13px; + margin-top: 0; +} + +#book-appointment-wizard .active-step strong { + color: #429a82; + font-size: 21px; +} + +#book-appointment-wizard #frame-footer { + padding: 15px; + text-align: center; + border-top: 1px solid #ebeef1; +} + +#book-appointment-wizard #steps .custom-qtip { + border-width: 2px; +} + +#book-appointment-wizard #available-hours { + overflow: auto; + margin: 15px 0; + padding-right: 10px; + width: auto; + max-height: 255px; +} + +#book-appointment-wizard #available-hours div { + margin-right: 30px; +} + +#book-appointment-wizard #available-hours .available-hour { + margin-bottom: 10px; +} + +#book-appointment-wizard #available-hours .selected-hour { + background-color: #439a82; + border-color: #439a82; + color: white; +} + +#book-appointment-wizard .span3 { + min-width: 270px; /* This is especially needed for ie8 */ +} + +#book-appointment-wizard #select-timezone { + margin-bottom: 15px; +} + +#book-appointment-wizard #appointment-details p, +#book-appointment-wizard #customer-details p { + font-size: 16px; + line-height: 28px; +} + +#book-appointment-wizard #wizard-frame-1 label { + font-size: 19px; + margin-bottom: 12px; +} + +#book-appointment-wizard #wizard-frame-1 select { + margin-bottom: 25px; +} + +#book-appointment-wizard .captcha-title { + float: left; + margin: 7px 0 10px 0; +} + +#book-appointment-wizard .captcha-title .fa-sync-alt { + cursor: pointer; + transition: all 0.3s linear; +} + +#book-appointment-wizard .captcha-title .fa-sync-alt:hover { + color: #1A865F; +} + +#book-appointment-wizard .captcha-image { + float: left; + margin-bottom: 20px; + border-radius: 3px; + box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.4); +} + +#book-appointment-wizard .captcha-text { + width: 100%; + margin-bottom: 20px; +} + +#book-appointment-wizard #service-description { + overflow-y: auto; + clear: both; + max-height: 153px; + box-shadow: none; +} + +#book-appointment-wizard #select-language, +#book-appointment-wizard .backend-link { + display: block; + min-width: 120px; + margin: 15px auto; + padding: 5px; +} + +.popover .popover-title { + text-align: center; +} + +.popover .popover-content #language-list .language { + margin: 15px 0; +} + +@media (min-width: 768px) { + .wrapper { + min-height: 100vh; + } + + #book-appointment-wizard { + border-radius: .25rem; + overflow: hidden; + box-shadow: rgba(45, 62, 80, 0.12) 0 1px 5px 0; + } + + #book-appointment-wizard #company-name { + display: inline-block; + float: left; + margin: 10px auto; + } + + #book-appointment-wizard #steps { + display: inline-block; + float: right; + margin: 5px auto; + } + + #book-appointment-wizard .wizard-frame { + padding: 10px 20px; + } + + #book-appointment-wizard .wizard-frame .command-buttons { + display: flex; + justify-content: space-between; + } + + #book-appointment-wizard .captcha-title { + margin-right: 20px; + margin-top: 7px; + } + + #book-appointment-wizard .captcha-image { + float: right; + } + + #book-appointment-wizard #select-language { + width: 100px; + padding: 5px; + margin: 5px auto; + } + + #book-appointment-wizard #frame-footer small { + display: flex; + } + + #book-appointment-wizard .footer-powered-by, + #book-appointment-wizard .footer-options { + width: 50%; + } + + #book-appointment-wizard .footer-powered-by { + text-align: left; + padding: 5px 5px 5px 0; + } + + #book-appointment-wizard .footer-options { + text-align: right; + } + + #book-appointment-wizard #select-language { + display: inline-block; + margin-right: 15px; + } + + #book-appointment-wizard .backend-link { + display: inline-block; + min-width: 120px; + padding: 5px; + margin: 5px auto; + } +} + +/* BOOK SUCCESS & MESSAGE + ------------------------------------------------------------------------- */ + +#message-frame, +#success-frame { + background: #FFF; + border: 1px solid #DDDADA; + padding: 70px; +} + +#message-frame #message-icon, +#success-frame #success-icon { + margin-top: 20px; + margin-right: 20px; +} + +#message-frame .alert, +#success-frame .alert { + margin-top: 20px; +} + +#message-frame, +#success-frame { + text-align: center; + height: auto; + border: none; + padding: 35px; +} + +#message-frame #message-icon, +#success-frame #success-icon { + width: 64px; + display: block; + margin: auto; + float: none !important; +} + +#success-frame .btn { + margin-bottom: 10px; + width: 80%; + max-width: 250px; +} + +@media (min-width: 768px) { + #message-frame, + #success-frame { + height: 100%; + } +} + +/* CANCEL APPOINTMENT + ------------------------------------------------------------------------- */ + +.booking-header-bar { + padding: 15px 0; + margin: 0; + background: #f3f2e7; + border-bottom: 1px solid #e4e1c9; + text-align: center; +} + +.ui-dialog .ui-dialog-title { + font-size: 1.2em; +} + +@media (min-width: 768px) { + .booking-header-bar { + padding: 15px 0; + margin: 0; + background: #f3f2e7; + border-bottom: 1px solid #e4e1c9; + text-align: left; + } +} + + diff --git a/assets/css/general.css b/assets/css/general.css new file mode 100644 index 00000000..4fc0841d --- /dev/null +++ b/assets/css/general.css @@ -0,0 +1,438 @@ +/* ---------------------------------------------------------------------------- + * Easy!Appointments - Open Source Web Scheduler + * + * @package EasyAppointments + * @author A.Tselegidis + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +@-moz-document url-prefix() { + body .checkbox input[type="checkbox"] { + float: left; + } +} + +body .custom-qtip { + border: none; + border-radius: 0; + padding: 10px; + box-shadow: 1px 1px 3px #767676; + background: #EFFDF6; + font-size: 12px; + line-height: 20px; + color: #258D53; +} + +body .ui-widget { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + font-size: 1.1em; +} + +body .ui-widget-overlay { + background: #000 50% 50% repeat-x; + opacity: .5; + filter: Alpha(Opacity=50); +} + +body .ui-dialog .ui-dialog-titlebar-close { + display: none; +} + +body .ui-draggable .ui-dialog-titlebar { + background: #429a82; + color: #FFF; + font-size: 1.2em; + font-weight: lighter; + padding: 12px 10px; + margin-bottom: 10px; + border: none; + border-radius: 0; +} + +body .ui-dialog { + padding: 0; + z-index: 2000; + border: none !important; + box-shadow: 0 0 10px #333; +} + +body .ui-dialog .ui-dialog-buttonpane { + padding: .3em 1em .3em .4em; + border: none; +} + +body .ui-dialog .ui-dialog-buttonpane .btn { + min-width: 120px; +} + +body .ui-button .ui-icon, +body .ui-button:hover .ui-icon { + background-image: url('../ext/jquery-ui/images/ui-icons_222222_256x240.png'); +} + +body .ui-dialog #error-technical { + max-width: 500px; +} + +body .ui-widget.ui-widget-content { + border: 1px solid #429a82; + padding: 0; +} + +body #ui-datepicker-div { + margin-top: 5px; + z-index: 1100 !important; +} + +body .ui-datepicker { + width: auto; + max-width: 288px; +} + +body .ui-datepicker .ui-widget-header { + border: none; + background: #429a82; + border-radius: 0; +} + +body .ui-datepicker .ui-widget-header .ui-icon { + background-image: url("../ext/jquery-ui/images/ui-icons_ffffff_256x240.png") +} + +body .ui-datepicker .ui-datepicker-title { + color: white; + padding: 8px 5px; +} + +body .ui-datepicker th { + background: #429a82; + color: #FFF; +} + +body .ui-datepicker tbody tr:first-child td { + margin-top: 5px; +} + +body .ui-datepicker td a, +body .ui-datepicker td span { + border: none !important; + background: none !important; + color: #1A865F !important; + text-align: center !important; + width: 32px; + height: 32px; + line-height: 2; +} + +html body .ui-datepicker td a.ui-state-active { + color: #FFF !important; + font-weight: bold !important; + background: #429a82 !important; + border-radius: 50px; + width: 24px; + height: 24px; + line-height: 1.2; + margin: 4px; +} + +body .ui-datepicker td a.ui-state-highlight { + background: #80E3AD !important; + border-radius: 67px; + color: #FFF !important; + width: 24px; + height: 24px; + line-height: 1.2; + margin: 4px; + +} + +body .ui-datepicker .ui-datepicker-prev-hover { + top: 2px !important; + left: 2px !important; + background: #80e1ac; + border-color: #80e1ac; + border-radius: 0; + cursor: pointer; +} + +body .ui-datepicker .ui-datepicker-next-hover { + top: 2px !important; + right: 2px !important; + background: #80e1ac; + border-color: #80e1ac; + border-radius: 0; + cursor: pointer; +} + +body .ui-datepicker .ui-slider-handle { + border-radius: none; + border-color: #429a82; + background-color: #429a82; +} + +body .ui-priority-primary, +body .ui-widget-content .ui-priority-primary, +body .ui-widget-header .ui-priority-primary { + font-weight: normal; +} + +body .ui-widget input, .ui-widget select, +body .ui-widget textarea, +body .ui-widget button { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + font-size: 1rem; +} + +body .ui-datepicker .ui-datepicker-buttonpane button { + padding: 6px 16px; +} + +.breaks tr:hover td { + background: #FFFFC2 !important; +} + +.working-plan td { + vertical-align: middle; +} + +.breaks td { + vertical-align: middle; +} + +li.language { + cursor: pointer; +} + +li.language:hover { + color: #005580; +} + +#select-language { + cursor: pointer; + display: inline-block; + padding: 5px; +} + +#language-list { + list-style: none; + padding-left: 0px; + max-height: 500px; + overflow-y: auto; +} + +/* JQUERY UI DATETIME PICKER ADDON + ------------------------------------------------------------------------- */ + +.ui-timepicker-div .ui-widget-header { + margin-bottom: 8px; +} + +.ui-timepicker-div dl { + text-align: left; +} + +.ui-timepicker-div dl dt { + float: left; + clear: left; + padding: 0 0 0 5px; +} + +.ui-timepicker-div dl dd { + margin: 0 10px 10px 40%; +} + +.ui-timepicker-div dl dd.ui_tpicker_time { + margin-bottom: 4px; +} + +.ui-timepicker-div dl dd.ui_tpicker_hour, +.ui-timepicker-div dl dd.ui_tpicker_minute { + padding-top: 8px; +} + +.ui-timepicker-div td { + font-size: 90%; +} + +.ui-tpicker-grid-label { + background: none; + border: none; + margin: 0; + padding: 0; +} + +.ui-timepicker-div .ui_tpicker_unit_hide { + display: none; +} + +.ui-timepicker-div .ui_tpicker_time .ui_tpicker_time_input { + background: none; + color: inherit; + border: none; + outline: none; + width: 95%; +} + +.ui-timepicker-div .ui_tpicker_time .ui_tpicker_time_input:focus { + border-bottom-color: #aaa; +} + +.ui-timepicker-rtl { + direction: rtl; +} + +.ui-timepicker-rtl dl { + text-align: right; + padding: 0 5px 0 0; +} + +.ui-timepicker-rtl dl dt { + float: right; + clear: right; +} + +.ui-timepicker-rtl dl dd { + margin: 0 40% 10px 10px; +} + +/* Shortened version style */ +.ui-timepicker-div.ui-timepicker-oneLine { + padding-right: 2px; +} + +.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time, +.ui-timepicker-div.ui-timepicker-oneLine dt { + display: none; +} + +.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time_label { + display: block; + padding-top: 2px; +} + +.ui-timepicker-div.ui-timepicker-oneLine dl { + text-align: right; +} + +.ui-timepicker-div.ui-timepicker-oneLine dl dd, +.ui-timepicker-div.ui-timepicker-oneLine dl dd > div { + display: inline-block; + margin: 0; +} + +.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_minute:before, +.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_second:before { + content: ':'; + display: inline-block; +} + +.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_millisec:before, +.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_microsec:before { + content: '.'; + display: inline-block; +} + +.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_unit_hide, +.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_unit_hide:before { + display: none; +} + +/* LOADING SPINNER + ------------------------------------------------------------------------- */ + +.is-loading { + position: relative; +} + +.is-loading:before, +.is-loading:after { + content: ''; + position: absolute; + top: 50%; + left: 50%; +} + +.animation:after { + width: 60px; + height: 60px; + margin: -25px 0 0 -25px; + + border: 5px solid rgba(0, 0, 0, .4); + border-radius: 50px; +} + +.animation:after { + border-bottom-color: transparent; + animation: spin 1s infinite linear; +} + +@keyframes spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +@keyframes spin-reverse { + from { + transform: rotate(0deg); + } + to { + transform: rotate(-360deg); + } +} + +.any-element { + width: 60px; + height: 60px; + position: fixed; + left: 50vw; + top: 50vh; + margin-left: -30px; + margin-bottom: -30px; +} + +#message-box pre, +#message-box .card { + max-height: 250px; + max-width: 500px; +} + +body .popover { + max-width: 300px; +} + +body .popover-body strong { + min-width: 90px; + display:inline-block; +} + +body .popover-body button { + font-size: 1em; + box-sizing: border-box; + margin: 0; + height: 2.1em; + padding: 0 .6em; +} + +body .popover-body a { + margin-right: 5px; +} + +.has-error .control-label, +.has-error label { + color: #dc3545; +} + +.has-error .form-control { + border-color: #dc3545; +} + +body .clearfix { + clear: both; +} diff --git a/src/engine/index.html b/assets/css/index.html similarity index 100% rename from src/engine/index.html rename to assets/css/index.html diff --git a/assets/css/installation.css b/assets/css/installation.css new file mode 100644 index 00000000..80164eea --- /dev/null +++ b/assets/css/installation.css @@ -0,0 +1,35 @@ +header { + background: #DAFFEB; + margin-bottom: 25px; +} + +.content { + margin: 32px; + max-width: 980px; +} + +.alert { + margin: 25px 0 10px 0; +} + +footer { + padding: 10px 35px; + background-color: #FAFAFA; + margin-top: 20px; + border-top: 1px solid #EEE; +} + +#loading { + position: fixed; + top: 0px; + left: 0px; + width: 100%; + height: 100%; + z-index: 999999; + background: rgba(255, 255, 255, 0.75); +} + +#loading img { + margin: auto; + display: block; +} diff --git a/assets/css/login.css b/assets/css/login.css new file mode 100644 index 00000000..6620c353 --- /dev/null +++ b/assets/css/login.css @@ -0,0 +1,22 @@ +body { + width: 100vw; + height: 100vh; + display: table-cell; + vertical-align: middle; + background-color: #f5f8fa; +} + +#login-frame { + width: 630px; + margin: auto; + background: #FFF; + border: 1px solid #DDDADA; + padding: 70px; +} + +@media(max-width: 640px) { + #login-frame { + width: 100%; + padding: 20px; + } +} diff --git a/assets/css/logout.css b/assets/css/logout.css new file mode 100644 index 00000000..0b5c9a03 --- /dev/null +++ b/assets/css/logout.css @@ -0,0 +1,31 @@ +body { + width: 100vw; + height: 100vh; + display: table-cell; + vertical-align: middle; + background-color: #f5f8fa; +} + +#logout-frame { + width: 630px; + margin: auto; + background: #FFF; + border: 1px solid #DDDADA; + padding: 70px; +} + +.btn { + margin-right: 10px; +} + +@media(max-width: 640px) { + #logout-frame { + width: 100%; + padding: 20px; + } + + .btn { + width: 100%; + margin-bottom: 20px; + } +} diff --git a/assets/css/no_privileges.php.css b/assets/css/no_privileges.php.css new file mode 100644 index 00000000..895826ec --- /dev/null +++ b/assets/css/no_privileges.php.css @@ -0,0 +1,31 @@ +body { + width: 100vw; + height: 100vh; + display: table-cell; + vertical-align: middle; + background-color: #f5f8fa; +} + +#no-priv-frame { + width: 630px; + margin: auto; + background: #FFF; + border: 1px solid #DDDADA; + padding: 70px; +} + +.btn { + margin-right: 10px; +} + +@media(max-width: 640px) { + #no-priv-frame { + width: 100%; + padding: 20px; + } + + .btn { + width: 100%; + margin-bottom: 20px; + } +} diff --git a/assets/css/update.css b/assets/css/update.css new file mode 100644 index 00000000..46341b0f --- /dev/null +++ b/assets/css/update.css @@ -0,0 +1,24 @@ +html { + position: relative; + min-height: 100%; +} + +.header { + background: #DAFFEB; +} + +h3 { + margin-bottom: 40px; +} + +.content { + margin-top: 30px; +} + +footer { + position: absolute; + bottom: 0; + width: 100%; + background-color: #f5f5f5; + padding: 15px 40px; +} diff --git a/assets/ext/bootstrap/css/bootstrap-grid.css b/assets/ext/bootstrap/css/bootstrap-grid.css new file mode 100644 index 00000000..40ee85d9 --- /dev/null +++ b/assets/ext/bootstrap/css/bootstrap-grid.css @@ -0,0 +1,3904 @@ +/*! + * Bootstrap Grid v4.5.0 (https://getbootstrap.com/) + * Copyright 2011-2020 The Bootstrap Authors + * Copyright 2011-2020 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +html { + box-sizing: border-box; + -ms-overflow-style: scrollbar; +} + +*, +*::before, +*::after { + box-sizing: inherit; +} + +.container { + width: 100%; + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} + +@media (min-width: 576px) { + .container { + max-width: 540px; + } +} + +@media (min-width: 768px) { + .container { + max-width: 720px; + } +} + +@media (min-width: 992px) { + .container { + max-width: 960px; + } +} + +@media (min-width: 1200px) { + .container { + max-width: 1140px; + } +} + +.container-fluid, .container-sm, .container-md, .container-lg, .container-xl { + width: 100%; + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} + +@media (min-width: 576px) { + .container, .container-sm { + max-width: 540px; + } +} + +@media (min-width: 768px) { + .container, .container-sm, .container-md { + max-width: 720px; + } +} + +@media (min-width: 992px) { + .container, .container-sm, .container-md, .container-lg { + max-width: 960px; + } +} + +@media (min-width: 1200px) { + .container, .container-sm, .container-md, .container-lg, .container-xl { + max-width: 1140px; + } +} + +.row { + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin-right: -15px; + margin-left: -15px; +} + +.no-gutters { + margin-right: 0; + margin-left: 0; +} + +.no-gutters > .col, +.no-gutters > [class*="col-"] { + padding-right: 0; + padding-left: 0; +} + +.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col, +.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm, +.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md, +.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg, +.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl, +.col-xl-auto { + position: relative; + width: 100%; + padding-right: 15px; + padding-left: 15px; +} + +.col { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + min-width: 0; + max-width: 100%; +} + +.row-cols-1 > * { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; +} + +.row-cols-2 > * { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; +} + +.row-cols-3 > * { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; +} + +.row-cols-4 > * { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; +} + +.row-cols-5 > * { + -ms-flex: 0 0 20%; + flex: 0 0 20%; + max-width: 20%; +} + +.row-cols-6 > * { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; +} + +.col-auto { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: 100%; +} + +.col-1 { + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333%; +} + +.col-2 { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; +} + +.col-3 { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; +} + +.col-4 { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; +} + +.col-5 { + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667%; +} + +.col-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; +} + +.col-7 { + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333%; +} + +.col-8 { + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667%; +} + +.col-9 { + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; +} + +.col-10 { + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333%; +} + +.col-11 { + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667%; +} + +.col-12 { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; +} + +.order-first { + -ms-flex-order: -1; + order: -1; +} + +.order-last { + -ms-flex-order: 13; + order: 13; +} + +.order-0 { + -ms-flex-order: 0; + order: 0; +} + +.order-1 { + -ms-flex-order: 1; + order: 1; +} + +.order-2 { + -ms-flex-order: 2; + order: 2; +} + +.order-3 { + -ms-flex-order: 3; + order: 3; +} + +.order-4 { + -ms-flex-order: 4; + order: 4; +} + +.order-5 { + -ms-flex-order: 5; + order: 5; +} + +.order-6 { + -ms-flex-order: 6; + order: 6; +} + +.order-7 { + -ms-flex-order: 7; + order: 7; +} + +.order-8 { + -ms-flex-order: 8; + order: 8; +} + +.order-9 { + -ms-flex-order: 9; + order: 9; +} + +.order-10 { + -ms-flex-order: 10; + order: 10; +} + +.order-11 { + -ms-flex-order: 11; + order: 11; +} + +.order-12 { + -ms-flex-order: 12; + order: 12; +} + +.offset-1 { + margin-left: 8.333333%; +} + +.offset-2 { + margin-left: 16.666667%; +} + +.offset-3 { + margin-left: 25%; +} + +.offset-4 { + margin-left: 33.333333%; +} + +.offset-5 { + margin-left: 41.666667%; +} + +.offset-6 { + margin-left: 50%; +} + +.offset-7 { + margin-left: 58.333333%; +} + +.offset-8 { + margin-left: 66.666667%; +} + +.offset-9 { + margin-left: 75%; +} + +.offset-10 { + margin-left: 83.333333%; +} + +.offset-11 { + margin-left: 91.666667%; +} + +@media (min-width: 576px) { + .col-sm { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + min-width: 0; + max-width: 100%; + } + .row-cols-sm-1 > * { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .row-cols-sm-2 > * { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .row-cols-sm-3 > * { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; + } + .row-cols-sm-4 > * { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .row-cols-sm-5 > * { + -ms-flex: 0 0 20%; + flex: 0 0 20%; + max-width: 20%; + } + .row-cols-sm-6 > * { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; + } + .col-sm-auto { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: 100%; + } + .col-sm-1 { + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333%; + } + .col-sm-2 { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; + } + .col-sm-3 { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .col-sm-4 { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; + } + .col-sm-5 { + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667%; + } + .col-sm-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .col-sm-7 { + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333%; + } + .col-sm-8 { + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667%; + } + .col-sm-9 { + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; + } + .col-sm-10 { + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333%; + } + .col-sm-11 { + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667%; + } + .col-sm-12 { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .order-sm-first { + -ms-flex-order: -1; + order: -1; + } + .order-sm-last { + -ms-flex-order: 13; + order: 13; + } + .order-sm-0 { + -ms-flex-order: 0; + order: 0; + } + .order-sm-1 { + -ms-flex-order: 1; + order: 1; + } + .order-sm-2 { + -ms-flex-order: 2; + order: 2; + } + .order-sm-3 { + -ms-flex-order: 3; + order: 3; + } + .order-sm-4 { + -ms-flex-order: 4; + order: 4; + } + .order-sm-5 { + -ms-flex-order: 5; + order: 5; + } + .order-sm-6 { + -ms-flex-order: 6; + order: 6; + } + .order-sm-7 { + -ms-flex-order: 7; + order: 7; + } + .order-sm-8 { + -ms-flex-order: 8; + order: 8; + } + .order-sm-9 { + -ms-flex-order: 9; + order: 9; + } + .order-sm-10 { + -ms-flex-order: 10; + order: 10; + } + .order-sm-11 { + -ms-flex-order: 11; + order: 11; + } + .order-sm-12 { + -ms-flex-order: 12; + order: 12; + } + .offset-sm-0 { + margin-left: 0; + } + .offset-sm-1 { + margin-left: 8.333333%; + } + .offset-sm-2 { + margin-left: 16.666667%; + } + .offset-sm-3 { + margin-left: 25%; + } + .offset-sm-4 { + margin-left: 33.333333%; + } + .offset-sm-5 { + margin-left: 41.666667%; + } + .offset-sm-6 { + margin-left: 50%; + } + .offset-sm-7 { + margin-left: 58.333333%; + } + .offset-sm-8 { + margin-left: 66.666667%; + } + .offset-sm-9 { + margin-left: 75%; + } + .offset-sm-10 { + margin-left: 83.333333%; + } + .offset-sm-11 { + margin-left: 91.666667%; + } +} + +@media (min-width: 768px) { + .col-md { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + min-width: 0; + max-width: 100%; + } + .row-cols-md-1 > * { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .row-cols-md-2 > * { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .row-cols-md-3 > * { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; + } + .row-cols-md-4 > * { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .row-cols-md-5 > * { + -ms-flex: 0 0 20%; + flex: 0 0 20%; + max-width: 20%; + } + .row-cols-md-6 > * { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; + } + .col-md-auto { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: 100%; + } + .col-md-1 { + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333%; + } + .col-md-2 { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; + } + .col-md-3 { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .col-md-4 { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; + } + .col-md-5 { + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667%; + } + .col-md-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .col-md-7 { + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333%; + } + .col-md-8 { + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667%; + } + .col-md-9 { + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; + } + .col-md-10 { + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333%; + } + .col-md-11 { + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667%; + } + .col-md-12 { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .order-md-first { + -ms-flex-order: -1; + order: -1; + } + .order-md-last { + -ms-flex-order: 13; + order: 13; + } + .order-md-0 { + -ms-flex-order: 0; + order: 0; + } + .order-md-1 { + -ms-flex-order: 1; + order: 1; + } + .order-md-2 { + -ms-flex-order: 2; + order: 2; + } + .order-md-3 { + -ms-flex-order: 3; + order: 3; + } + .order-md-4 { + -ms-flex-order: 4; + order: 4; + } + .order-md-5 { + -ms-flex-order: 5; + order: 5; + } + .order-md-6 { + -ms-flex-order: 6; + order: 6; + } + .order-md-7 { + -ms-flex-order: 7; + order: 7; + } + .order-md-8 { + -ms-flex-order: 8; + order: 8; + } + .order-md-9 { + -ms-flex-order: 9; + order: 9; + } + .order-md-10 { + -ms-flex-order: 10; + order: 10; + } + .order-md-11 { + -ms-flex-order: 11; + order: 11; + } + .order-md-12 { + -ms-flex-order: 12; + order: 12; + } + .offset-md-0 { + margin-left: 0; + } + .offset-md-1 { + margin-left: 8.333333%; + } + .offset-md-2 { + margin-left: 16.666667%; + } + .offset-md-3 { + margin-left: 25%; + } + .offset-md-4 { + margin-left: 33.333333%; + } + .offset-md-5 { + margin-left: 41.666667%; + } + .offset-md-6 { + margin-left: 50%; + } + .offset-md-7 { + margin-left: 58.333333%; + } + .offset-md-8 { + margin-left: 66.666667%; + } + .offset-md-9 { + margin-left: 75%; + } + .offset-md-10 { + margin-left: 83.333333%; + } + .offset-md-11 { + margin-left: 91.666667%; + } +} + +@media (min-width: 992px) { + .col-lg { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + min-width: 0; + max-width: 100%; + } + .row-cols-lg-1 > * { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .row-cols-lg-2 > * { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .row-cols-lg-3 > * { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; + } + .row-cols-lg-4 > * { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .row-cols-lg-5 > * { + -ms-flex: 0 0 20%; + flex: 0 0 20%; + max-width: 20%; + } + .row-cols-lg-6 > * { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; + } + .col-lg-auto { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: 100%; + } + .col-lg-1 { + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333%; + } + .col-lg-2 { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; + } + .col-lg-3 { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .col-lg-4 { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; + } + .col-lg-5 { + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667%; + } + .col-lg-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .col-lg-7 { + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333%; + } + .col-lg-8 { + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667%; + } + .col-lg-9 { + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; + } + .col-lg-10 { + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333%; + } + .col-lg-11 { + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667%; + } + .col-lg-12 { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .order-lg-first { + -ms-flex-order: -1; + order: -1; + } + .order-lg-last { + -ms-flex-order: 13; + order: 13; + } + .order-lg-0 { + -ms-flex-order: 0; + order: 0; + } + .order-lg-1 { + -ms-flex-order: 1; + order: 1; + } + .order-lg-2 { + -ms-flex-order: 2; + order: 2; + } + .order-lg-3 { + -ms-flex-order: 3; + order: 3; + } + .order-lg-4 { + -ms-flex-order: 4; + order: 4; + } + .order-lg-5 { + -ms-flex-order: 5; + order: 5; + } + .order-lg-6 { + -ms-flex-order: 6; + order: 6; + } + .order-lg-7 { + -ms-flex-order: 7; + order: 7; + } + .order-lg-8 { + -ms-flex-order: 8; + order: 8; + } + .order-lg-9 { + -ms-flex-order: 9; + order: 9; + } + .order-lg-10 { + -ms-flex-order: 10; + order: 10; + } + .order-lg-11 { + -ms-flex-order: 11; + order: 11; + } + .order-lg-12 { + -ms-flex-order: 12; + order: 12; + } + .offset-lg-0 { + margin-left: 0; + } + .offset-lg-1 { + margin-left: 8.333333%; + } + .offset-lg-2 { + margin-left: 16.666667%; + } + .offset-lg-3 { + margin-left: 25%; + } + .offset-lg-4 { + margin-left: 33.333333%; + } + .offset-lg-5 { + margin-left: 41.666667%; + } + .offset-lg-6 { + margin-left: 50%; + } + .offset-lg-7 { + margin-left: 58.333333%; + } + .offset-lg-8 { + margin-left: 66.666667%; + } + .offset-lg-9 { + margin-left: 75%; + } + .offset-lg-10 { + margin-left: 83.333333%; + } + .offset-lg-11 { + margin-left: 91.666667%; + } +} + +@media (min-width: 1200px) { + .col-xl { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + min-width: 0; + max-width: 100%; + } + .row-cols-xl-1 > * { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .row-cols-xl-2 > * { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .row-cols-xl-3 > * { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; + } + .row-cols-xl-4 > * { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .row-cols-xl-5 > * { + -ms-flex: 0 0 20%; + flex: 0 0 20%; + max-width: 20%; + } + .row-cols-xl-6 > * { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; + } + .col-xl-auto { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: 100%; + } + .col-xl-1 { + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333%; + } + .col-xl-2 { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; + } + .col-xl-3 { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .col-xl-4 { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; + } + .col-xl-5 { + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667%; + } + .col-xl-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .col-xl-7 { + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333%; + } + .col-xl-8 { + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667%; + } + .col-xl-9 { + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; + } + .col-xl-10 { + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333%; + } + .col-xl-11 { + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667%; + } + .col-xl-12 { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .order-xl-first { + -ms-flex-order: -1; + order: -1; + } + .order-xl-last { + -ms-flex-order: 13; + order: 13; + } + .order-xl-0 { + -ms-flex-order: 0; + order: 0; + } + .order-xl-1 { + -ms-flex-order: 1; + order: 1; + } + .order-xl-2 { + -ms-flex-order: 2; + order: 2; + } + .order-xl-3 { + -ms-flex-order: 3; + order: 3; + } + .order-xl-4 { + -ms-flex-order: 4; + order: 4; + } + .order-xl-5 { + -ms-flex-order: 5; + order: 5; + } + .order-xl-6 { + -ms-flex-order: 6; + order: 6; + } + .order-xl-7 { + -ms-flex-order: 7; + order: 7; + } + .order-xl-8 { + -ms-flex-order: 8; + order: 8; + } + .order-xl-9 { + -ms-flex-order: 9; + order: 9; + } + .order-xl-10 { + -ms-flex-order: 10; + order: 10; + } + .order-xl-11 { + -ms-flex-order: 11; + order: 11; + } + .order-xl-12 { + -ms-flex-order: 12; + order: 12; + } + .offset-xl-0 { + margin-left: 0; + } + .offset-xl-1 { + margin-left: 8.333333%; + } + .offset-xl-2 { + margin-left: 16.666667%; + } + .offset-xl-3 { + margin-left: 25%; + } + .offset-xl-4 { + margin-left: 33.333333%; + } + .offset-xl-5 { + margin-left: 41.666667%; + } + .offset-xl-6 { + margin-left: 50%; + } + .offset-xl-7 { + margin-left: 58.333333%; + } + .offset-xl-8 { + margin-left: 66.666667%; + } + .offset-xl-9 { + margin-left: 75%; + } + .offset-xl-10 { + margin-left: 83.333333%; + } + .offset-xl-11 { + margin-left: 91.666667%; + } +} + +.d-none { + display: none !important; +} + +.d-inline { + display: inline !important; +} + +.d-inline-block { + display: inline-block !important; +} + +.d-block { + display: block !important; +} + +.d-table { + display: table !important; +} + +.d-table-row { + display: table-row !important; +} + +.d-table-cell { + display: table-cell !important; +} + +.d-flex { + display: -ms-flexbox !important; + display: flex !important; +} + +.d-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; +} + +@media (min-width: 576px) { + .d-sm-none { + display: none !important; + } + .d-sm-inline { + display: inline !important; + } + .d-sm-inline-block { + display: inline-block !important; + } + .d-sm-block { + display: block !important; + } + .d-sm-table { + display: table !important; + } + .d-sm-table-row { + display: table-row !important; + } + .d-sm-table-cell { + display: table-cell !important; + } + .d-sm-flex { + display: -ms-flexbox !important; + display: flex !important; + } + .d-sm-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +@media (min-width: 768px) { + .d-md-none { + display: none !important; + } + .d-md-inline { + display: inline !important; + } + .d-md-inline-block { + display: inline-block !important; + } + .d-md-block { + display: block !important; + } + .d-md-table { + display: table !important; + } + .d-md-table-row { + display: table-row !important; + } + .d-md-table-cell { + display: table-cell !important; + } + .d-md-flex { + display: -ms-flexbox !important; + display: flex !important; + } + .d-md-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +@media (min-width: 992px) { + .d-lg-none { + display: none !important; + } + .d-lg-inline { + display: inline !important; + } + .d-lg-inline-block { + display: inline-block !important; + } + .d-lg-block { + display: block !important; + } + .d-lg-table { + display: table !important; + } + .d-lg-table-row { + display: table-row !important; + } + .d-lg-table-cell { + display: table-cell !important; + } + .d-lg-flex { + display: -ms-flexbox !important; + display: flex !important; + } + .d-lg-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +@media (min-width: 1200px) { + .d-xl-none { + display: none !important; + } + .d-xl-inline { + display: inline !important; + } + .d-xl-inline-block { + display: inline-block !important; + } + .d-xl-block { + display: block !important; + } + .d-xl-table { + display: table !important; + } + .d-xl-table-row { + display: table-row !important; + } + .d-xl-table-cell { + display: table-cell !important; + } + .d-xl-flex { + display: -ms-flexbox !important; + display: flex !important; + } + .d-xl-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +@media print { + .d-print-none { + display: none !important; + } + .d-print-inline { + display: inline !important; + } + .d-print-inline-block { + display: inline-block !important; + } + .d-print-block { + display: block !important; + } + .d-print-table { + display: table !important; + } + .d-print-table-row { + display: table-row !important; + } + .d-print-table-cell { + display: table-cell !important; + } + .d-print-flex { + display: -ms-flexbox !important; + display: flex !important; + } + .d-print-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +.flex-row { + -ms-flex-direction: row !important; + flex-direction: row !important; +} + +.flex-column { + -ms-flex-direction: column !important; + flex-direction: column !important; +} + +.flex-row-reverse { + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; +} + +.flex-column-reverse { + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; +} + +.flex-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; +} + +.flex-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; +} + +.flex-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; +} + +.flex-fill { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; +} + +.flex-grow-0 { + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; +} + +.flex-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; +} + +.flex-shrink-0 { + -ms-flex-negative: 0 !important; + flex-shrink: 0 !important; +} + +.flex-shrink-1 { + -ms-flex-negative: 1 !important; + flex-shrink: 1 !important; +} + +.justify-content-start { + -ms-flex-pack: start !important; + justify-content: flex-start !important; +} + +.justify-content-end { + -ms-flex-pack: end !important; + justify-content: flex-end !important; +} + +.justify-content-center { + -ms-flex-pack: center !important; + justify-content: center !important; +} + +.justify-content-between { + -ms-flex-pack: justify !important; + justify-content: space-between !important; +} + +.justify-content-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; +} + +.align-items-start { + -ms-flex-align: start !important; + align-items: flex-start !important; +} + +.align-items-end { + -ms-flex-align: end !important; + align-items: flex-end !important; +} + +.align-items-center { + -ms-flex-align: center !important; + align-items: center !important; +} + +.align-items-baseline { + -ms-flex-align: baseline !important; + align-items: baseline !important; +} + +.align-items-stretch { + -ms-flex-align: stretch !important; + align-items: stretch !important; +} + +.align-content-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; +} + +.align-content-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; +} + +.align-content-center { + -ms-flex-line-pack: center !important; + align-content: center !important; +} + +.align-content-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; +} + +.align-content-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; +} + +.align-content-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; +} + +.align-self-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; +} + +.align-self-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; +} + +.align-self-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; +} + +.align-self-center { + -ms-flex-item-align: center !important; + align-self: center !important; +} + +.align-self-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; +} + +.align-self-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; +} + +@media (min-width: 576px) { + .flex-sm-row { + -ms-flex-direction: row !important; + flex-direction: row !important; + } + .flex-sm-column { + -ms-flex-direction: column !important; + flex-direction: column !important; + } + .flex-sm-row-reverse { + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; + } + .flex-sm-column-reverse { + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; + } + .flex-sm-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; + } + .flex-sm-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; + } + .flex-sm-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; + } + .flex-sm-fill { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; + } + .flex-sm-grow-0 { + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; + } + .flex-sm-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; + } + .flex-sm-shrink-0 { + -ms-flex-negative: 0 !important; + flex-shrink: 0 !important; + } + .flex-sm-shrink-1 { + -ms-flex-negative: 1 !important; + flex-shrink: 1 !important; + } + .justify-content-sm-start { + -ms-flex-pack: start !important; + justify-content: flex-start !important; + } + .justify-content-sm-end { + -ms-flex-pack: end !important; + justify-content: flex-end !important; + } + .justify-content-sm-center { + -ms-flex-pack: center !important; + justify-content: center !important; + } + .justify-content-sm-between { + -ms-flex-pack: justify !important; + justify-content: space-between !important; + } + .justify-content-sm-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; + } + .align-items-sm-start { + -ms-flex-align: start !important; + align-items: flex-start !important; + } + .align-items-sm-end { + -ms-flex-align: end !important; + align-items: flex-end !important; + } + .align-items-sm-center { + -ms-flex-align: center !important; + align-items: center !important; + } + .align-items-sm-baseline { + -ms-flex-align: baseline !important; + align-items: baseline !important; + } + .align-items-sm-stretch { + -ms-flex-align: stretch !important; + align-items: stretch !important; + } + .align-content-sm-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; + } + .align-content-sm-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; + } + .align-content-sm-center { + -ms-flex-line-pack: center !important; + align-content: center !important; + } + .align-content-sm-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; + } + .align-content-sm-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; + } + .align-content-sm-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; + } + .align-self-sm-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; + } + .align-self-sm-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; + } + .align-self-sm-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; + } + .align-self-sm-center { + -ms-flex-item-align: center !important; + align-self: center !important; + } + .align-self-sm-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; + } + .align-self-sm-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; + } +} + +@media (min-width: 768px) { + .flex-md-row { + -ms-flex-direction: row !important; + flex-direction: row !important; + } + .flex-md-column { + -ms-flex-direction: column !important; + flex-direction: column !important; + } + .flex-md-row-reverse { + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; + } + .flex-md-column-reverse { + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; + } + .flex-md-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; + } + .flex-md-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; + } + .flex-md-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; + } + .flex-md-fill { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; + } + .flex-md-grow-0 { + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; + } + .flex-md-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; + } + .flex-md-shrink-0 { + -ms-flex-negative: 0 !important; + flex-shrink: 0 !important; + } + .flex-md-shrink-1 { + -ms-flex-negative: 1 !important; + flex-shrink: 1 !important; + } + .justify-content-md-start { + -ms-flex-pack: start !important; + justify-content: flex-start !important; + } + .justify-content-md-end { + -ms-flex-pack: end !important; + justify-content: flex-end !important; + } + .justify-content-md-center { + -ms-flex-pack: center !important; + justify-content: center !important; + } + .justify-content-md-between { + -ms-flex-pack: justify !important; + justify-content: space-between !important; + } + .justify-content-md-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; + } + .align-items-md-start { + -ms-flex-align: start !important; + align-items: flex-start !important; + } + .align-items-md-end { + -ms-flex-align: end !important; + align-items: flex-end !important; + } + .align-items-md-center { + -ms-flex-align: center !important; + align-items: center !important; + } + .align-items-md-baseline { + -ms-flex-align: baseline !important; + align-items: baseline !important; + } + .align-items-md-stretch { + -ms-flex-align: stretch !important; + align-items: stretch !important; + } + .align-content-md-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; + } + .align-content-md-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; + } + .align-content-md-center { + -ms-flex-line-pack: center !important; + align-content: center !important; + } + .align-content-md-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; + } + .align-content-md-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; + } + .align-content-md-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; + } + .align-self-md-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; + } + .align-self-md-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; + } + .align-self-md-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; + } + .align-self-md-center { + -ms-flex-item-align: center !important; + align-self: center !important; + } + .align-self-md-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; + } + .align-self-md-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; + } +} + +@media (min-width: 992px) { + .flex-lg-row { + -ms-flex-direction: row !important; + flex-direction: row !important; + } + .flex-lg-column { + -ms-flex-direction: column !important; + flex-direction: column !important; + } + .flex-lg-row-reverse { + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; + } + .flex-lg-column-reverse { + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; + } + .flex-lg-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; + } + .flex-lg-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; + } + .flex-lg-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; + } + .flex-lg-fill { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; + } + .flex-lg-grow-0 { + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; + } + .flex-lg-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; + } + .flex-lg-shrink-0 { + -ms-flex-negative: 0 !important; + flex-shrink: 0 !important; + } + .flex-lg-shrink-1 { + -ms-flex-negative: 1 !important; + flex-shrink: 1 !important; + } + .justify-content-lg-start { + -ms-flex-pack: start !important; + justify-content: flex-start !important; + } + .justify-content-lg-end { + -ms-flex-pack: end !important; + justify-content: flex-end !important; + } + .justify-content-lg-center { + -ms-flex-pack: center !important; + justify-content: center !important; + } + .justify-content-lg-between { + -ms-flex-pack: justify !important; + justify-content: space-between !important; + } + .justify-content-lg-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; + } + .align-items-lg-start { + -ms-flex-align: start !important; + align-items: flex-start !important; + } + .align-items-lg-end { + -ms-flex-align: end !important; + align-items: flex-end !important; + } + .align-items-lg-center { + -ms-flex-align: center !important; + align-items: center !important; + } + .align-items-lg-baseline { + -ms-flex-align: baseline !important; + align-items: baseline !important; + } + .align-items-lg-stretch { + -ms-flex-align: stretch !important; + align-items: stretch !important; + } + .align-content-lg-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; + } + .align-content-lg-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; + } + .align-content-lg-center { + -ms-flex-line-pack: center !important; + align-content: center !important; + } + .align-content-lg-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; + } + .align-content-lg-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; + } + .align-content-lg-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; + } + .align-self-lg-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; + } + .align-self-lg-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; + } + .align-self-lg-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; + } + .align-self-lg-center { + -ms-flex-item-align: center !important; + align-self: center !important; + } + .align-self-lg-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; + } + .align-self-lg-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; + } +} + +@media (min-width: 1200px) { + .flex-xl-row { + -ms-flex-direction: row !important; + flex-direction: row !important; + } + .flex-xl-column { + -ms-flex-direction: column !important; + flex-direction: column !important; + } + .flex-xl-row-reverse { + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; + } + .flex-xl-column-reverse { + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; + } + .flex-xl-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; + } + .flex-xl-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; + } + .flex-xl-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; + } + .flex-xl-fill { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; + } + .flex-xl-grow-0 { + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; + } + .flex-xl-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; + } + .flex-xl-shrink-0 { + -ms-flex-negative: 0 !important; + flex-shrink: 0 !important; + } + .flex-xl-shrink-1 { + -ms-flex-negative: 1 !important; + flex-shrink: 1 !important; + } + .justify-content-xl-start { + -ms-flex-pack: start !important; + justify-content: flex-start !important; + } + .justify-content-xl-end { + -ms-flex-pack: end !important; + justify-content: flex-end !important; + } + .justify-content-xl-center { + -ms-flex-pack: center !important; + justify-content: center !important; + } + .justify-content-xl-between { + -ms-flex-pack: justify !important; + justify-content: space-between !important; + } + .justify-content-xl-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; + } + .align-items-xl-start { + -ms-flex-align: start !important; + align-items: flex-start !important; + } + .align-items-xl-end { + -ms-flex-align: end !important; + align-items: flex-end !important; + } + .align-items-xl-center { + -ms-flex-align: center !important; + align-items: center !important; + } + .align-items-xl-baseline { + -ms-flex-align: baseline !important; + align-items: baseline !important; + } + .align-items-xl-stretch { + -ms-flex-align: stretch !important; + align-items: stretch !important; + } + .align-content-xl-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; + } + .align-content-xl-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; + } + .align-content-xl-center { + -ms-flex-line-pack: center !important; + align-content: center !important; + } + .align-content-xl-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; + } + .align-content-xl-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; + } + .align-content-xl-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; + } + .align-self-xl-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; + } + .align-self-xl-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; + } + .align-self-xl-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; + } + .align-self-xl-center { + -ms-flex-item-align: center !important; + align-self: center !important; + } + .align-self-xl-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; + } + .align-self-xl-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; + } +} + +.m-0 { + margin: 0 !important; +} + +.mt-0, +.my-0 { + margin-top: 0 !important; +} + +.mr-0, +.mx-0 { + margin-right: 0 !important; +} + +.mb-0, +.my-0 { + margin-bottom: 0 !important; +} + +.ml-0, +.mx-0 { + margin-left: 0 !important; +} + +.m-1 { + margin: 0.25rem !important; +} + +.mt-1, +.my-1 { + margin-top: 0.25rem !important; +} + +.mr-1, +.mx-1 { + margin-right: 0.25rem !important; +} + +.mb-1, +.my-1 { + margin-bottom: 0.25rem !important; +} + +.ml-1, +.mx-1 { + margin-left: 0.25rem !important; +} + +.m-2 { + margin: 0.5rem !important; +} + +.mt-2, +.my-2 { + margin-top: 0.5rem !important; +} + +.mr-2, +.mx-2 { + margin-right: 0.5rem !important; +} + +.mb-2, +.my-2 { + margin-bottom: 0.5rem !important; +} + +.ml-2, +.mx-2 { + margin-left: 0.5rem !important; +} + +.m-3 { + margin: 1rem !important; +} + +.mt-3, +.my-3 { + margin-top: 1rem !important; +} + +.mr-3, +.mx-3 { + margin-right: 1rem !important; +} + +.mb-3, +.my-3 { + margin-bottom: 1rem !important; +} + +.ml-3, +.mx-3 { + margin-left: 1rem !important; +} + +.m-4 { + margin: 1.5rem !important; +} + +.mt-4, +.my-4 { + margin-top: 1.5rem !important; +} + +.mr-4, +.mx-4 { + margin-right: 1.5rem !important; +} + +.mb-4, +.my-4 { + margin-bottom: 1.5rem !important; +} + +.ml-4, +.mx-4 { + margin-left: 1.5rem !important; +} + +.m-5 { + margin: 3rem !important; +} + +.mt-5, +.my-5 { + margin-top: 3rem !important; +} + +.mr-5, +.mx-5 { + margin-right: 3rem !important; +} + +.mb-5, +.my-5 { + margin-bottom: 3rem !important; +} + +.ml-5, +.mx-5 { + margin-left: 3rem !important; +} + +.p-0 { + padding: 0 !important; +} + +.pt-0, +.py-0 { + padding-top: 0 !important; +} + +.pr-0, +.px-0 { + padding-right: 0 !important; +} + +.pb-0, +.py-0 { + padding-bottom: 0 !important; +} + +.pl-0, +.px-0 { + padding-left: 0 !important; +} + +.p-1 { + padding: 0.25rem !important; +} + +.pt-1, +.py-1 { + padding-top: 0.25rem !important; +} + +.pr-1, +.px-1 { + padding-right: 0.25rem !important; +} + +.pb-1, +.py-1 { + padding-bottom: 0.25rem !important; +} + +.pl-1, +.px-1 { + padding-left: 0.25rem !important; +} + +.p-2 { + padding: 0.5rem !important; +} + +.pt-2, +.py-2 { + padding-top: 0.5rem !important; +} + +.pr-2, +.px-2 { + padding-right: 0.5rem !important; +} + +.pb-2, +.py-2 { + padding-bottom: 0.5rem !important; +} + +.pl-2, +.px-2 { + padding-left: 0.5rem !important; +} + +.p-3 { + padding: 1rem !important; +} + +.pt-3, +.py-3 { + padding-top: 1rem !important; +} + +.pr-3, +.px-3 { + padding-right: 1rem !important; +} + +.pb-3, +.py-3 { + padding-bottom: 1rem !important; +} + +.pl-3, +.px-3 { + padding-left: 1rem !important; +} + +.p-4 { + padding: 1.5rem !important; +} + +.pt-4, +.py-4 { + padding-top: 1.5rem !important; +} + +.pr-4, +.px-4 { + padding-right: 1.5rem !important; +} + +.pb-4, +.py-4 { + padding-bottom: 1.5rem !important; +} + +.pl-4, +.px-4 { + padding-left: 1.5rem !important; +} + +.p-5 { + padding: 3rem !important; +} + +.pt-5, +.py-5 { + padding-top: 3rem !important; +} + +.pr-5, +.px-5 { + padding-right: 3rem !important; +} + +.pb-5, +.py-5 { + padding-bottom: 3rem !important; +} + +.pl-5, +.px-5 { + padding-left: 3rem !important; +} + +.m-n1 { + margin: -0.25rem !important; +} + +.mt-n1, +.my-n1 { + margin-top: -0.25rem !important; +} + +.mr-n1, +.mx-n1 { + margin-right: -0.25rem !important; +} + +.mb-n1, +.my-n1 { + margin-bottom: -0.25rem !important; +} + +.ml-n1, +.mx-n1 { + margin-left: -0.25rem !important; +} + +.m-n2 { + margin: -0.5rem !important; +} + +.mt-n2, +.my-n2 { + margin-top: -0.5rem !important; +} + +.mr-n2, +.mx-n2 { + margin-right: -0.5rem !important; +} + +.mb-n2, +.my-n2 { + margin-bottom: -0.5rem !important; +} + +.ml-n2, +.mx-n2 { + margin-left: -0.5rem !important; +} + +.m-n3 { + margin: -1rem !important; +} + +.mt-n3, +.my-n3 { + margin-top: -1rem !important; +} + +.mr-n3, +.mx-n3 { + margin-right: -1rem !important; +} + +.mb-n3, +.my-n3 { + margin-bottom: -1rem !important; +} + +.ml-n3, +.mx-n3 { + margin-left: -1rem !important; +} + +.m-n4 { + margin: -1.5rem !important; +} + +.mt-n4, +.my-n4 { + margin-top: -1.5rem !important; +} + +.mr-n4, +.mx-n4 { + margin-right: -1.5rem !important; +} + +.mb-n4, +.my-n4 { + margin-bottom: -1.5rem !important; +} + +.ml-n4, +.mx-n4 { + margin-left: -1.5rem !important; +} + +.m-n5 { + margin: -3rem !important; +} + +.mt-n5, +.my-n5 { + margin-top: -3rem !important; +} + +.mr-n5, +.mx-n5 { + margin-right: -3rem !important; +} + +.mb-n5, +.my-n5 { + margin-bottom: -3rem !important; +} + +.ml-n5, +.mx-n5 { + margin-left: -3rem !important; +} + +.m-auto { + margin: auto !important; +} + +.mt-auto, +.my-auto { + margin-top: auto !important; +} + +.mr-auto, +.mx-auto { + margin-right: auto !important; +} + +.mb-auto, +.my-auto { + margin-bottom: auto !important; +} + +.ml-auto, +.mx-auto { + margin-left: auto !important; +} + +@media (min-width: 576px) { + .m-sm-0 { + margin: 0 !important; + } + .mt-sm-0, + .my-sm-0 { + margin-top: 0 !important; + } + .mr-sm-0, + .mx-sm-0 { + margin-right: 0 !important; + } + .mb-sm-0, + .my-sm-0 { + margin-bottom: 0 !important; + } + .ml-sm-0, + .mx-sm-0 { + margin-left: 0 !important; + } + .m-sm-1 { + margin: 0.25rem !important; + } + .mt-sm-1, + .my-sm-1 { + margin-top: 0.25rem !important; + } + .mr-sm-1, + .mx-sm-1 { + margin-right: 0.25rem !important; + } + .mb-sm-1, + .my-sm-1 { + margin-bottom: 0.25rem !important; + } + .ml-sm-1, + .mx-sm-1 { + margin-left: 0.25rem !important; + } + .m-sm-2 { + margin: 0.5rem !important; + } + .mt-sm-2, + .my-sm-2 { + margin-top: 0.5rem !important; + } + .mr-sm-2, + .mx-sm-2 { + margin-right: 0.5rem !important; + } + .mb-sm-2, + .my-sm-2 { + margin-bottom: 0.5rem !important; + } + .ml-sm-2, + .mx-sm-2 { + margin-left: 0.5rem !important; + } + .m-sm-3 { + margin: 1rem !important; + } + .mt-sm-3, + .my-sm-3 { + margin-top: 1rem !important; + } + .mr-sm-3, + .mx-sm-3 { + margin-right: 1rem !important; + } + .mb-sm-3, + .my-sm-3 { + margin-bottom: 1rem !important; + } + .ml-sm-3, + .mx-sm-3 { + margin-left: 1rem !important; + } + .m-sm-4 { + margin: 1.5rem !important; + } + .mt-sm-4, + .my-sm-4 { + margin-top: 1.5rem !important; + } + .mr-sm-4, + .mx-sm-4 { + margin-right: 1.5rem !important; + } + .mb-sm-4, + .my-sm-4 { + margin-bottom: 1.5rem !important; + } + .ml-sm-4, + .mx-sm-4 { + margin-left: 1.5rem !important; + } + .m-sm-5 { + margin: 3rem !important; + } + .mt-sm-5, + .my-sm-5 { + margin-top: 3rem !important; + } + .mr-sm-5, + .mx-sm-5 { + margin-right: 3rem !important; + } + .mb-sm-5, + .my-sm-5 { + margin-bottom: 3rem !important; + } + .ml-sm-5, + .mx-sm-5 { + margin-left: 3rem !important; + } + .p-sm-0 { + padding: 0 !important; + } + .pt-sm-0, + .py-sm-0 { + padding-top: 0 !important; + } + .pr-sm-0, + .px-sm-0 { + padding-right: 0 !important; + } + .pb-sm-0, + .py-sm-0 { + padding-bottom: 0 !important; + } + .pl-sm-0, + .px-sm-0 { + padding-left: 0 !important; + } + .p-sm-1 { + padding: 0.25rem !important; + } + .pt-sm-1, + .py-sm-1 { + padding-top: 0.25rem !important; + } + .pr-sm-1, + .px-sm-1 { + padding-right: 0.25rem !important; + } + .pb-sm-1, + .py-sm-1 { + padding-bottom: 0.25rem !important; + } + .pl-sm-1, + .px-sm-1 { + padding-left: 0.25rem !important; + } + .p-sm-2 { + padding: 0.5rem !important; + } + .pt-sm-2, + .py-sm-2 { + padding-top: 0.5rem !important; + } + .pr-sm-2, + .px-sm-2 { + padding-right: 0.5rem !important; + } + .pb-sm-2, + .py-sm-2 { + padding-bottom: 0.5rem !important; + } + .pl-sm-2, + .px-sm-2 { + padding-left: 0.5rem !important; + } + .p-sm-3 { + padding: 1rem !important; + } + .pt-sm-3, + .py-sm-3 { + padding-top: 1rem !important; + } + .pr-sm-3, + .px-sm-3 { + padding-right: 1rem !important; + } + .pb-sm-3, + .py-sm-3 { + padding-bottom: 1rem !important; + } + .pl-sm-3, + .px-sm-3 { + padding-left: 1rem !important; + } + .p-sm-4 { + padding: 1.5rem !important; + } + .pt-sm-4, + .py-sm-4 { + padding-top: 1.5rem !important; + } + .pr-sm-4, + .px-sm-4 { + padding-right: 1.5rem !important; + } + .pb-sm-4, + .py-sm-4 { + padding-bottom: 1.5rem !important; + } + .pl-sm-4, + .px-sm-4 { + padding-left: 1.5rem !important; + } + .p-sm-5 { + padding: 3rem !important; + } + .pt-sm-5, + .py-sm-5 { + padding-top: 3rem !important; + } + .pr-sm-5, + .px-sm-5 { + padding-right: 3rem !important; + } + .pb-sm-5, + .py-sm-5 { + padding-bottom: 3rem !important; + } + .pl-sm-5, + .px-sm-5 { + padding-left: 3rem !important; + } + .m-sm-n1 { + margin: -0.25rem !important; + } + .mt-sm-n1, + .my-sm-n1 { + margin-top: -0.25rem !important; + } + .mr-sm-n1, + .mx-sm-n1 { + margin-right: -0.25rem !important; + } + .mb-sm-n1, + .my-sm-n1 { + margin-bottom: -0.25rem !important; + } + .ml-sm-n1, + .mx-sm-n1 { + margin-left: -0.25rem !important; + } + .m-sm-n2 { + margin: -0.5rem !important; + } + .mt-sm-n2, + .my-sm-n2 { + margin-top: -0.5rem !important; + } + .mr-sm-n2, + .mx-sm-n2 { + margin-right: -0.5rem !important; + } + .mb-sm-n2, + .my-sm-n2 { + margin-bottom: -0.5rem !important; + } + .ml-sm-n2, + .mx-sm-n2 { + margin-left: -0.5rem !important; + } + .m-sm-n3 { + margin: -1rem !important; + } + .mt-sm-n3, + .my-sm-n3 { + margin-top: -1rem !important; + } + .mr-sm-n3, + .mx-sm-n3 { + margin-right: -1rem !important; + } + .mb-sm-n3, + .my-sm-n3 { + margin-bottom: -1rem !important; + } + .ml-sm-n3, + .mx-sm-n3 { + margin-left: -1rem !important; + } + .m-sm-n4 { + margin: -1.5rem !important; + } + .mt-sm-n4, + .my-sm-n4 { + margin-top: -1.5rem !important; + } + .mr-sm-n4, + .mx-sm-n4 { + margin-right: -1.5rem !important; + } + .mb-sm-n4, + .my-sm-n4 { + margin-bottom: -1.5rem !important; + } + .ml-sm-n4, + .mx-sm-n4 { + margin-left: -1.5rem !important; + } + .m-sm-n5 { + margin: -3rem !important; + } + .mt-sm-n5, + .my-sm-n5 { + margin-top: -3rem !important; + } + .mr-sm-n5, + .mx-sm-n5 { + margin-right: -3rem !important; + } + .mb-sm-n5, + .my-sm-n5 { + margin-bottom: -3rem !important; + } + .ml-sm-n5, + .mx-sm-n5 { + margin-left: -3rem !important; + } + .m-sm-auto { + margin: auto !important; + } + .mt-sm-auto, + .my-sm-auto { + margin-top: auto !important; + } + .mr-sm-auto, + .mx-sm-auto { + margin-right: auto !important; + } + .mb-sm-auto, + .my-sm-auto { + margin-bottom: auto !important; + } + .ml-sm-auto, + .mx-sm-auto { + margin-left: auto !important; + } +} + +@media (min-width: 768px) { + .m-md-0 { + margin: 0 !important; + } + .mt-md-0, + .my-md-0 { + margin-top: 0 !important; + } + .mr-md-0, + .mx-md-0 { + margin-right: 0 !important; + } + .mb-md-0, + .my-md-0 { + margin-bottom: 0 !important; + } + .ml-md-0, + .mx-md-0 { + margin-left: 0 !important; + } + .m-md-1 { + margin: 0.25rem !important; + } + .mt-md-1, + .my-md-1 { + margin-top: 0.25rem !important; + } + .mr-md-1, + .mx-md-1 { + margin-right: 0.25rem !important; + } + .mb-md-1, + .my-md-1 { + margin-bottom: 0.25rem !important; + } + .ml-md-1, + .mx-md-1 { + margin-left: 0.25rem !important; + } + .m-md-2 { + margin: 0.5rem !important; + } + .mt-md-2, + .my-md-2 { + margin-top: 0.5rem !important; + } + .mr-md-2, + .mx-md-2 { + margin-right: 0.5rem !important; + } + .mb-md-2, + .my-md-2 { + margin-bottom: 0.5rem !important; + } + .ml-md-2, + .mx-md-2 { + margin-left: 0.5rem !important; + } + .m-md-3 { + margin: 1rem !important; + } + .mt-md-3, + .my-md-3 { + margin-top: 1rem !important; + } + .mr-md-3, + .mx-md-3 { + margin-right: 1rem !important; + } + .mb-md-3, + .my-md-3 { + margin-bottom: 1rem !important; + } + .ml-md-3, + .mx-md-3 { + margin-left: 1rem !important; + } + .m-md-4 { + margin: 1.5rem !important; + } + .mt-md-4, + .my-md-4 { + margin-top: 1.5rem !important; + } + .mr-md-4, + .mx-md-4 { + margin-right: 1.5rem !important; + } + .mb-md-4, + .my-md-4 { + margin-bottom: 1.5rem !important; + } + .ml-md-4, + .mx-md-4 { + margin-left: 1.5rem !important; + } + .m-md-5 { + margin: 3rem !important; + } + .mt-md-5, + .my-md-5 { + margin-top: 3rem !important; + } + .mr-md-5, + .mx-md-5 { + margin-right: 3rem !important; + } + .mb-md-5, + .my-md-5 { + margin-bottom: 3rem !important; + } + .ml-md-5, + .mx-md-5 { + margin-left: 3rem !important; + } + .p-md-0 { + padding: 0 !important; + } + .pt-md-0, + .py-md-0 { + padding-top: 0 !important; + } + .pr-md-0, + .px-md-0 { + padding-right: 0 !important; + } + .pb-md-0, + .py-md-0 { + padding-bottom: 0 !important; + } + .pl-md-0, + .px-md-0 { + padding-left: 0 !important; + } + .p-md-1 { + padding: 0.25rem !important; + } + .pt-md-1, + .py-md-1 { + padding-top: 0.25rem !important; + } + .pr-md-1, + .px-md-1 { + padding-right: 0.25rem !important; + } + .pb-md-1, + .py-md-1 { + padding-bottom: 0.25rem !important; + } + .pl-md-1, + .px-md-1 { + padding-left: 0.25rem !important; + } + .p-md-2 { + padding: 0.5rem !important; + } + .pt-md-2, + .py-md-2 { + padding-top: 0.5rem !important; + } + .pr-md-2, + .px-md-2 { + padding-right: 0.5rem !important; + } + .pb-md-2, + .py-md-2 { + padding-bottom: 0.5rem !important; + } + .pl-md-2, + .px-md-2 { + padding-left: 0.5rem !important; + } + .p-md-3 { + padding: 1rem !important; + } + .pt-md-3, + .py-md-3 { + padding-top: 1rem !important; + } + .pr-md-3, + .px-md-3 { + padding-right: 1rem !important; + } + .pb-md-3, + .py-md-3 { + padding-bottom: 1rem !important; + } + .pl-md-3, + .px-md-3 { + padding-left: 1rem !important; + } + .p-md-4 { + padding: 1.5rem !important; + } + .pt-md-4, + .py-md-4 { + padding-top: 1.5rem !important; + } + .pr-md-4, + .px-md-4 { + padding-right: 1.5rem !important; + } + .pb-md-4, + .py-md-4 { + padding-bottom: 1.5rem !important; + } + .pl-md-4, + .px-md-4 { + padding-left: 1.5rem !important; + } + .p-md-5 { + padding: 3rem !important; + } + .pt-md-5, + .py-md-5 { + padding-top: 3rem !important; + } + .pr-md-5, + .px-md-5 { + padding-right: 3rem !important; + } + .pb-md-5, + .py-md-5 { + padding-bottom: 3rem !important; + } + .pl-md-5, + .px-md-5 { + padding-left: 3rem !important; + } + .m-md-n1 { + margin: -0.25rem !important; + } + .mt-md-n1, + .my-md-n1 { + margin-top: -0.25rem !important; + } + .mr-md-n1, + .mx-md-n1 { + margin-right: -0.25rem !important; + } + .mb-md-n1, + .my-md-n1 { + margin-bottom: -0.25rem !important; + } + .ml-md-n1, + .mx-md-n1 { + margin-left: -0.25rem !important; + } + .m-md-n2 { + margin: -0.5rem !important; + } + .mt-md-n2, + .my-md-n2 { + margin-top: -0.5rem !important; + } + .mr-md-n2, + .mx-md-n2 { + margin-right: -0.5rem !important; + } + .mb-md-n2, + .my-md-n2 { + margin-bottom: -0.5rem !important; + } + .ml-md-n2, + .mx-md-n2 { + margin-left: -0.5rem !important; + } + .m-md-n3 { + margin: -1rem !important; + } + .mt-md-n3, + .my-md-n3 { + margin-top: -1rem !important; + } + .mr-md-n3, + .mx-md-n3 { + margin-right: -1rem !important; + } + .mb-md-n3, + .my-md-n3 { + margin-bottom: -1rem !important; + } + .ml-md-n3, + .mx-md-n3 { + margin-left: -1rem !important; + } + .m-md-n4 { + margin: -1.5rem !important; + } + .mt-md-n4, + .my-md-n4 { + margin-top: -1.5rem !important; + } + .mr-md-n4, + .mx-md-n4 { + margin-right: -1.5rem !important; + } + .mb-md-n4, + .my-md-n4 { + margin-bottom: -1.5rem !important; + } + .ml-md-n4, + .mx-md-n4 { + margin-left: -1.5rem !important; + } + .m-md-n5 { + margin: -3rem !important; + } + .mt-md-n5, + .my-md-n5 { + margin-top: -3rem !important; + } + .mr-md-n5, + .mx-md-n5 { + margin-right: -3rem !important; + } + .mb-md-n5, + .my-md-n5 { + margin-bottom: -3rem !important; + } + .ml-md-n5, + .mx-md-n5 { + margin-left: -3rem !important; + } + .m-md-auto { + margin: auto !important; + } + .mt-md-auto, + .my-md-auto { + margin-top: auto !important; + } + .mr-md-auto, + .mx-md-auto { + margin-right: auto !important; + } + .mb-md-auto, + .my-md-auto { + margin-bottom: auto !important; + } + .ml-md-auto, + .mx-md-auto { + margin-left: auto !important; + } +} + +@media (min-width: 992px) { + .m-lg-0 { + margin: 0 !important; + } + .mt-lg-0, + .my-lg-0 { + margin-top: 0 !important; + } + .mr-lg-0, + .mx-lg-0 { + margin-right: 0 !important; + } + .mb-lg-0, + .my-lg-0 { + margin-bottom: 0 !important; + } + .ml-lg-0, + .mx-lg-0 { + margin-left: 0 !important; + } + .m-lg-1 { + margin: 0.25rem !important; + } + .mt-lg-1, + .my-lg-1 { + margin-top: 0.25rem !important; + } + .mr-lg-1, + .mx-lg-1 { + margin-right: 0.25rem !important; + } + .mb-lg-1, + .my-lg-1 { + margin-bottom: 0.25rem !important; + } + .ml-lg-1, + .mx-lg-1 { + margin-left: 0.25rem !important; + } + .m-lg-2 { + margin: 0.5rem !important; + } + .mt-lg-2, + .my-lg-2 { + margin-top: 0.5rem !important; + } + .mr-lg-2, + .mx-lg-2 { + margin-right: 0.5rem !important; + } + .mb-lg-2, + .my-lg-2 { + margin-bottom: 0.5rem !important; + } + .ml-lg-2, + .mx-lg-2 { + margin-left: 0.5rem !important; + } + .m-lg-3 { + margin: 1rem !important; + } + .mt-lg-3, + .my-lg-3 { + margin-top: 1rem !important; + } + .mr-lg-3, + .mx-lg-3 { + margin-right: 1rem !important; + } + .mb-lg-3, + .my-lg-3 { + margin-bottom: 1rem !important; + } + .ml-lg-3, + .mx-lg-3 { + margin-left: 1rem !important; + } + .m-lg-4 { + margin: 1.5rem !important; + } + .mt-lg-4, + .my-lg-4 { + margin-top: 1.5rem !important; + } + .mr-lg-4, + .mx-lg-4 { + margin-right: 1.5rem !important; + } + .mb-lg-4, + .my-lg-4 { + margin-bottom: 1.5rem !important; + } + .ml-lg-4, + .mx-lg-4 { + margin-left: 1.5rem !important; + } + .m-lg-5 { + margin: 3rem !important; + } + .mt-lg-5, + .my-lg-5 { + margin-top: 3rem !important; + } + .mr-lg-5, + .mx-lg-5 { + margin-right: 3rem !important; + } + .mb-lg-5, + .my-lg-5 { + margin-bottom: 3rem !important; + } + .ml-lg-5, + .mx-lg-5 { + margin-left: 3rem !important; + } + .p-lg-0 { + padding: 0 !important; + } + .pt-lg-0, + .py-lg-0 { + padding-top: 0 !important; + } + .pr-lg-0, + .px-lg-0 { + padding-right: 0 !important; + } + .pb-lg-0, + .py-lg-0 { + padding-bottom: 0 !important; + } + .pl-lg-0, + .px-lg-0 { + padding-left: 0 !important; + } + .p-lg-1 { + padding: 0.25rem !important; + } + .pt-lg-1, + .py-lg-1 { + padding-top: 0.25rem !important; + } + .pr-lg-1, + .px-lg-1 { + padding-right: 0.25rem !important; + } + .pb-lg-1, + .py-lg-1 { + padding-bottom: 0.25rem !important; + } + .pl-lg-1, + .px-lg-1 { + padding-left: 0.25rem !important; + } + .p-lg-2 { + padding: 0.5rem !important; + } + .pt-lg-2, + .py-lg-2 { + padding-top: 0.5rem !important; + } + .pr-lg-2, + .px-lg-2 { + padding-right: 0.5rem !important; + } + .pb-lg-2, + .py-lg-2 { + padding-bottom: 0.5rem !important; + } + .pl-lg-2, + .px-lg-2 { + padding-left: 0.5rem !important; + } + .p-lg-3 { + padding: 1rem !important; + } + .pt-lg-3, + .py-lg-3 { + padding-top: 1rem !important; + } + .pr-lg-3, + .px-lg-3 { + padding-right: 1rem !important; + } + .pb-lg-3, + .py-lg-3 { + padding-bottom: 1rem !important; + } + .pl-lg-3, + .px-lg-3 { + padding-left: 1rem !important; + } + .p-lg-4 { + padding: 1.5rem !important; + } + .pt-lg-4, + .py-lg-4 { + padding-top: 1.5rem !important; + } + .pr-lg-4, + .px-lg-4 { + padding-right: 1.5rem !important; + } + .pb-lg-4, + .py-lg-4 { + padding-bottom: 1.5rem !important; + } + .pl-lg-4, + .px-lg-4 { + padding-left: 1.5rem !important; + } + .p-lg-5 { + padding: 3rem !important; + } + .pt-lg-5, + .py-lg-5 { + padding-top: 3rem !important; + } + .pr-lg-5, + .px-lg-5 { + padding-right: 3rem !important; + } + .pb-lg-5, + .py-lg-5 { + padding-bottom: 3rem !important; + } + .pl-lg-5, + .px-lg-5 { + padding-left: 3rem !important; + } + .m-lg-n1 { + margin: -0.25rem !important; + } + .mt-lg-n1, + .my-lg-n1 { + margin-top: -0.25rem !important; + } + .mr-lg-n1, + .mx-lg-n1 { + margin-right: -0.25rem !important; + } + .mb-lg-n1, + .my-lg-n1 { + margin-bottom: -0.25rem !important; + } + .ml-lg-n1, + .mx-lg-n1 { + margin-left: -0.25rem !important; + } + .m-lg-n2 { + margin: -0.5rem !important; + } + .mt-lg-n2, + .my-lg-n2 { + margin-top: -0.5rem !important; + } + .mr-lg-n2, + .mx-lg-n2 { + margin-right: -0.5rem !important; + } + .mb-lg-n2, + .my-lg-n2 { + margin-bottom: -0.5rem !important; + } + .ml-lg-n2, + .mx-lg-n2 { + margin-left: -0.5rem !important; + } + .m-lg-n3 { + margin: -1rem !important; + } + .mt-lg-n3, + .my-lg-n3 { + margin-top: -1rem !important; + } + .mr-lg-n3, + .mx-lg-n3 { + margin-right: -1rem !important; + } + .mb-lg-n3, + .my-lg-n3 { + margin-bottom: -1rem !important; + } + .ml-lg-n3, + .mx-lg-n3 { + margin-left: -1rem !important; + } + .m-lg-n4 { + margin: -1.5rem !important; + } + .mt-lg-n4, + .my-lg-n4 { + margin-top: -1.5rem !important; + } + .mr-lg-n4, + .mx-lg-n4 { + margin-right: -1.5rem !important; + } + .mb-lg-n4, + .my-lg-n4 { + margin-bottom: -1.5rem !important; + } + .ml-lg-n4, + .mx-lg-n4 { + margin-left: -1.5rem !important; + } + .m-lg-n5 { + margin: -3rem !important; + } + .mt-lg-n5, + .my-lg-n5 { + margin-top: -3rem !important; + } + .mr-lg-n5, + .mx-lg-n5 { + margin-right: -3rem !important; + } + .mb-lg-n5, + .my-lg-n5 { + margin-bottom: -3rem !important; + } + .ml-lg-n5, + .mx-lg-n5 { + margin-left: -3rem !important; + } + .m-lg-auto { + margin: auto !important; + } + .mt-lg-auto, + .my-lg-auto { + margin-top: auto !important; + } + .mr-lg-auto, + .mx-lg-auto { + margin-right: auto !important; + } + .mb-lg-auto, + .my-lg-auto { + margin-bottom: auto !important; + } + .ml-lg-auto, + .mx-lg-auto { + margin-left: auto !important; + } +} + +@media (min-width: 1200px) { + .m-xl-0 { + margin: 0 !important; + } + .mt-xl-0, + .my-xl-0 { + margin-top: 0 !important; + } + .mr-xl-0, + .mx-xl-0 { + margin-right: 0 !important; + } + .mb-xl-0, + .my-xl-0 { + margin-bottom: 0 !important; + } + .ml-xl-0, + .mx-xl-0 { + margin-left: 0 !important; + } + .m-xl-1 { + margin: 0.25rem !important; + } + .mt-xl-1, + .my-xl-1 { + margin-top: 0.25rem !important; + } + .mr-xl-1, + .mx-xl-1 { + margin-right: 0.25rem !important; + } + .mb-xl-1, + .my-xl-1 { + margin-bottom: 0.25rem !important; + } + .ml-xl-1, + .mx-xl-1 { + margin-left: 0.25rem !important; + } + .m-xl-2 { + margin: 0.5rem !important; + } + .mt-xl-2, + .my-xl-2 { + margin-top: 0.5rem !important; + } + .mr-xl-2, + .mx-xl-2 { + margin-right: 0.5rem !important; + } + .mb-xl-2, + .my-xl-2 { + margin-bottom: 0.5rem !important; + } + .ml-xl-2, + .mx-xl-2 { + margin-left: 0.5rem !important; + } + .m-xl-3 { + margin: 1rem !important; + } + .mt-xl-3, + .my-xl-3 { + margin-top: 1rem !important; + } + .mr-xl-3, + .mx-xl-3 { + margin-right: 1rem !important; + } + .mb-xl-3, + .my-xl-3 { + margin-bottom: 1rem !important; + } + .ml-xl-3, + .mx-xl-3 { + margin-left: 1rem !important; + } + .m-xl-4 { + margin: 1.5rem !important; + } + .mt-xl-4, + .my-xl-4 { + margin-top: 1.5rem !important; + } + .mr-xl-4, + .mx-xl-4 { + margin-right: 1.5rem !important; + } + .mb-xl-4, + .my-xl-4 { + margin-bottom: 1.5rem !important; + } + .ml-xl-4, + .mx-xl-4 { + margin-left: 1.5rem !important; + } + .m-xl-5 { + margin: 3rem !important; + } + .mt-xl-5, + .my-xl-5 { + margin-top: 3rem !important; + } + .mr-xl-5, + .mx-xl-5 { + margin-right: 3rem !important; + } + .mb-xl-5, + .my-xl-5 { + margin-bottom: 3rem !important; + } + .ml-xl-5, + .mx-xl-5 { + margin-left: 3rem !important; + } + .p-xl-0 { + padding: 0 !important; + } + .pt-xl-0, + .py-xl-0 { + padding-top: 0 !important; + } + .pr-xl-0, + .px-xl-0 { + padding-right: 0 !important; + } + .pb-xl-0, + .py-xl-0 { + padding-bottom: 0 !important; + } + .pl-xl-0, + .px-xl-0 { + padding-left: 0 !important; + } + .p-xl-1 { + padding: 0.25rem !important; + } + .pt-xl-1, + .py-xl-1 { + padding-top: 0.25rem !important; + } + .pr-xl-1, + .px-xl-1 { + padding-right: 0.25rem !important; + } + .pb-xl-1, + .py-xl-1 { + padding-bottom: 0.25rem !important; + } + .pl-xl-1, + .px-xl-1 { + padding-left: 0.25rem !important; + } + .p-xl-2 { + padding: 0.5rem !important; + } + .pt-xl-2, + .py-xl-2 { + padding-top: 0.5rem !important; + } + .pr-xl-2, + .px-xl-2 { + padding-right: 0.5rem !important; + } + .pb-xl-2, + .py-xl-2 { + padding-bottom: 0.5rem !important; + } + .pl-xl-2, + .px-xl-2 { + padding-left: 0.5rem !important; + } + .p-xl-3 { + padding: 1rem !important; + } + .pt-xl-3, + .py-xl-3 { + padding-top: 1rem !important; + } + .pr-xl-3, + .px-xl-3 { + padding-right: 1rem !important; + } + .pb-xl-3, + .py-xl-3 { + padding-bottom: 1rem !important; + } + .pl-xl-3, + .px-xl-3 { + padding-left: 1rem !important; + } + .p-xl-4 { + padding: 1.5rem !important; + } + .pt-xl-4, + .py-xl-4 { + padding-top: 1.5rem !important; + } + .pr-xl-4, + .px-xl-4 { + padding-right: 1.5rem !important; + } + .pb-xl-4, + .py-xl-4 { + padding-bottom: 1.5rem !important; + } + .pl-xl-4, + .px-xl-4 { + padding-left: 1.5rem !important; + } + .p-xl-5 { + padding: 3rem !important; + } + .pt-xl-5, + .py-xl-5 { + padding-top: 3rem !important; + } + .pr-xl-5, + .px-xl-5 { + padding-right: 3rem !important; + } + .pb-xl-5, + .py-xl-5 { + padding-bottom: 3rem !important; + } + .pl-xl-5, + .px-xl-5 { + padding-left: 3rem !important; + } + .m-xl-n1 { + margin: -0.25rem !important; + } + .mt-xl-n1, + .my-xl-n1 { + margin-top: -0.25rem !important; + } + .mr-xl-n1, + .mx-xl-n1 { + margin-right: -0.25rem !important; + } + .mb-xl-n1, + .my-xl-n1 { + margin-bottom: -0.25rem !important; + } + .ml-xl-n1, + .mx-xl-n1 { + margin-left: -0.25rem !important; + } + .m-xl-n2 { + margin: -0.5rem !important; + } + .mt-xl-n2, + .my-xl-n2 { + margin-top: -0.5rem !important; + } + .mr-xl-n2, + .mx-xl-n2 { + margin-right: -0.5rem !important; + } + .mb-xl-n2, + .my-xl-n2 { + margin-bottom: -0.5rem !important; + } + .ml-xl-n2, + .mx-xl-n2 { + margin-left: -0.5rem !important; + } + .m-xl-n3 { + margin: -1rem !important; + } + .mt-xl-n3, + .my-xl-n3 { + margin-top: -1rem !important; + } + .mr-xl-n3, + .mx-xl-n3 { + margin-right: -1rem !important; + } + .mb-xl-n3, + .my-xl-n3 { + margin-bottom: -1rem !important; + } + .ml-xl-n3, + .mx-xl-n3 { + margin-left: -1rem !important; + } + .m-xl-n4 { + margin: -1.5rem !important; + } + .mt-xl-n4, + .my-xl-n4 { + margin-top: -1.5rem !important; + } + .mr-xl-n4, + .mx-xl-n4 { + margin-right: -1.5rem !important; + } + .mb-xl-n4, + .my-xl-n4 { + margin-bottom: -1.5rem !important; + } + .ml-xl-n4, + .mx-xl-n4 { + margin-left: -1.5rem !important; + } + .m-xl-n5 { + margin: -3rem !important; + } + .mt-xl-n5, + .my-xl-n5 { + margin-top: -3rem !important; + } + .mr-xl-n5, + .mx-xl-n5 { + margin-right: -3rem !important; + } + .mb-xl-n5, + .my-xl-n5 { + margin-bottom: -3rem !important; + } + .ml-xl-n5, + .mx-xl-n5 { + margin-left: -3rem !important; + } + .m-xl-auto { + margin: auto !important; + } + .mt-xl-auto, + .my-xl-auto { + margin-top: auto !important; + } + .mr-xl-auto, + .mx-xl-auto { + margin-right: auto !important; + } + .mb-xl-auto, + .my-xl-auto { + margin-bottom: auto !important; + } + .ml-xl-auto, + .mx-xl-auto { + margin-left: auto !important; + } +} +/*# sourceMappingURL=bootstrap-grid.css.map */ \ No newline at end of file diff --git a/assets/ext/bootstrap/css/bootstrap-grid.css.map b/assets/ext/bootstrap/css/bootstrap-grid.css.map new file mode 100644 index 00000000..57efc43b --- /dev/null +++ b/assets/ext/bootstrap/css/bootstrap-grid.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../scss/bootstrap-grid.scss","bootstrap-grid.css","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/mixins/_breakpoints.scss","../../scss/_variables.scss","../../scss/mixins/_grid-framework.scss","../../scss/utilities/_display.scss","../../scss/utilities/_flex.scss","../../scss/utilities/_spacing.scss"],"names":[],"mappings":"AAAA;;;;;ECKE;ADEF;EACE,sBAAsB;EACtB,6BAA6B;ACA/B;;ADGA;;;EAGE,mBAAmB;ACArB;;ACTE;ECDA,WAAW;EACX,mBAA0B;EAC1B,kBAAyB;EACzB,kBAAkB;EAClB,iBAAiB;AFcnB;;AGqCI;EFtDF;ICWI,gBEuMK;EJ5LT;AACF;;AG+BI;EFtDF;ICWI,gBEwMK;EJvLT;AACF;;AGyBI;EFtDF;ICWI,gBEyMK;EJlLT;AACF;;AGmBI;EFtDF;ICWI,iBE0MM;EJ7KV;AACF;;ACnCE;ECPA,WAAW;EACX,mBAA0B;EAC1B,kBAAyB;EACzB,kBAAkB;EAClB,iBAAiB;AF8CnB;;AGKI;EFrCE;IACE,gBGgMG;EJ5JT;AACF;;AGDI;EFrCE;IACE,gBGiMG;EJvJT;AACF;;AGPI;EFrCE;IACE,gBGkMG;EJlJT;AACF;;AGbI;EFrCE;IACE,iBGmMI;EJ7IV;AACF;;AC3BE;EC7BA,oBAAa;EAAb,aAAa;EACb,mBAAe;EAAf,eAAe;EACf,mBAA0B;EAC1B,kBAAyB;AF4D3B;;AC5BE;EACE,eAAe;EACf,cAAc;AD+BlB;;ACjCE;;EAMI,gBAAgB;EAChB,eAAe;ADgCrB;;AK1FE;;;;;;EACE,kBAAkB;EAClB,WAAW;EACX,mBAA0B;EAC1B,kBAAyB;ALkG7B;;AK5EM;EACE,0BAAa;EAAb,aAAa;EACb,oBAAY;EAAZ,YAAY;EACZ,YAAY;EACZ,eAAe;AL+EvB;;AK1EU;EHuBN,kBAAuB;EAAvB,cAAuB;EACvB,eAAwB;AFuD5B;;AK/EU;EHuBN,iBAAuB;EAAvB,aAAuB;EACvB,cAAwB;AF4D5B;;AKpFU;EHuBN,wBAAuB;EAAvB,oBAAuB;EACvB,qBAAwB;AFiE5B;;AKzFU;EHuBN,iBAAuB;EAAvB,aAAuB;EACvB,cAAwB;AFsE5B;;AK9FU;EHuBN,iBAAuB;EAAvB,aAAuB;EACvB,cAAwB;AF2E5B;;AKnGU;EHuBN,wBAAuB;EAAvB,oBAAuB;EACvB,qBAAwB;AFgF5B;;AKlGM;EHAJ,kBAAc;EAAd,cAAc;EACd,WAAW;EACX,eAAe;AFsGjB;;AKlGU;EHdR,uBAAsC;EAAtC,mBAAsC;EAItC,oBAAuC;AFiHzC;;AKvGU;EHdR,wBAAsC;EAAtC,oBAAsC;EAItC,qBAAuC;AFsHzC;;AK5GU;EHdR,iBAAsC;EAAtC,aAAsC;EAItC,cAAuC;AF2HzC;;AKjHU;EHdR,wBAAsC;EAAtC,oBAAsC;EAItC,qBAAuC;AFgIzC;;AKtHU;EHdR,wBAAsC;EAAtC,oBAAsC;EAItC,qBAAuC;AFqIzC;;AK3HU;EHdR,iBAAsC;EAAtC,aAAsC;EAItC,cAAuC;AF0IzC;;AKhIU;EHdR,wBAAsC;EAAtC,oBAAsC;EAItC,qBAAuC;AF+IzC;;AKrIU;EHdR,wBAAsC;EAAtC,oBAAsC;EAItC,qBAAuC;AFoJzC;;AK1IU;EHdR,iBAAsC;EAAtC,aAAsC;EAItC,cAAuC;AFyJzC;;AK/IU;EHdR,wBAAsC;EAAtC,oBAAsC;EAItC,qBAAuC;AF8JzC;;AKpJU;EHdR,wBAAsC;EAAtC,oBAAsC;EAItC,qBAAuC;AFmKzC;;AKzJU;EHdR,kBAAsC;EAAtC,cAAsC;EAItC,eAAuC;AFwKzC;;AKxJM;EAAwB,kBAAS;EAAT,SAAS;AL4JvC;;AK1JM;EAAuB,kBDuKG;ECvKH,SDuKG;AJThC;;AK3JQ;EAAwB,iBADZ;EACY,QADZ;ALgKpB;;AK/JQ;EAAwB,iBADZ;EACY,QADZ;ALoKpB;;AKnKQ;EAAwB,iBADZ;EACY,QADZ;ALwKpB;;AKvKQ;EAAwB,iBADZ;EACY,QADZ;AL4KpB;;AK3KQ;EAAwB,iBADZ;EACY,QADZ;ALgLpB;;AK/KQ;EAAwB,iBADZ;EACY,QADZ;ALoLpB;;AKnLQ;EAAwB,iBADZ;EACY,QADZ;ALwLpB;;AKvLQ;EAAwB,iBADZ;EACY,QADZ;AL4LpB;;AK3LQ;EAAwB,iBADZ;EACY,QADZ;ALgMpB;;AK/LQ;EAAwB,iBADZ;EACY,QADZ;ALoMpB;;AKnMQ;EAAwB,kBADZ;EACY,SADZ;ALwMpB;;AKvMQ;EAAwB,kBADZ;EACY,SADZ;AL4MpB;;AK3MQ;EAAwB,kBADZ;EACY,SADZ;ALgNpB;;AKxMY;EHjBV,sBAA8C;AF6NhD;;AK5MY;EHjBV,uBAA8C;AFiOhD;;AKhNY;EHjBV,gBAA8C;AFqOhD;;AKpNY;EHjBV,uBAA8C;AFyOhD;;AKxNY;EHjBV,uBAA8C;AF6OhD;;AK5NY;EHjBV,gBAA8C;AFiPhD;;AKhOY;EHjBV,uBAA8C;AFqPhD;;AKpOY;EHjBV,uBAA8C;AFyPhD;;AKxOY;EHjBV,gBAA8C;AF6PhD;;AK5OY;EHjBV,uBAA8C;AFiQhD;;AKhPY;EHjBV,uBAA8C;AFqQhD;;AGhQI;EE3BE;IACE,0BAAa;IAAb,aAAa;IACb,oBAAY;IAAZ,YAAY;IACZ,YAAY;IACZ,eAAe;EL+RrB;EK1RQ;IHuBN,kBAAuB;IAAvB,cAAuB;IACvB,eAAwB;EFsQ1B;EK9RQ;IHuBN,iBAAuB;IAAvB,aAAuB;IACvB,cAAwB;EF0Q1B;EKlSQ;IHuBN,wBAAuB;IAAvB,oBAAuB;IACvB,qBAAwB;EF8Q1B;EKtSQ;IHuBN,iBAAuB;IAAvB,aAAuB;IACvB,cAAwB;EFkR1B;EK1SQ;IHuBN,iBAAuB;IAAvB,aAAuB;IACvB,cAAwB;EFsR1B;EK9SQ;IHuBN,wBAAuB;IAAvB,oBAAuB;IACvB,qBAAwB;EF0R1B;EK5SI;IHAJ,kBAAc;IAAd,cAAc;IACd,WAAW;IACX,eAAe;EF+Sf;EK3SQ;IHdR,uBAAsC;IAAtC,mBAAsC;IAItC,oBAAuC;EFyTvC;EK/SQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EF6TvC;EKnTQ;IHdR,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EFiUvC;EKvTQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFqUvC;EK3TQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFyUvC;EK/TQ;IHdR,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EF6UvC;EKnUQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFiVvC;EKvUQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFqVvC;EK3UQ;IHdR,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EFyVvC;EK/UQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EF6VvC;EKnVQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFiWvC;EKvVQ;IHdR,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;EFqWvC;EKrVI;IAAwB,kBAAS;IAAT,SAAS;ELwVrC;EKtVI;IAAuB,kBDuKG;ICvKH,SDuKG;EJkL9B;EKtVM;IAAwB,iBADZ;IACY,QADZ;EL0VlB;EKzVM;IAAwB,iBADZ;IACY,QADZ;EL6VlB;EK5VM;IAAwB,iBADZ;IACY,QADZ;ELgWlB;EK/VM;IAAwB,iBADZ;IACY,QADZ;ELmWlB;EKlWM;IAAwB,iBADZ;IACY,QADZ;ELsWlB;EKrWM;IAAwB,iBADZ;IACY,QADZ;ELyWlB;EKxWM;IAAwB,iBADZ;IACY,QADZ;EL4WlB;EK3WM;IAAwB,iBADZ;IACY,QADZ;EL+WlB;EK9WM;IAAwB,iBADZ;IACY,QADZ;ELkXlB;EKjXM;IAAwB,iBADZ;IACY,QADZ;ELqXlB;EKpXM;IAAwB,kBADZ;IACY,SADZ;ELwXlB;EKvXM;IAAwB,kBADZ;IACY,SADZ;EL2XlB;EK1XM;IAAwB,kBADZ;IACY,SADZ;EL8XlB;EKtXU;IHjBV,cAA4B;EF0Y5B;EKzXU;IHjBV,sBAA8C;EF6Y9C;EK5XU;IHjBV,uBAA8C;EFgZ9C;EK/XU;IHjBV,gBAA8C;EFmZ9C;EKlYU;IHjBV,uBAA8C;EFsZ9C;EKrYU;IHjBV,uBAA8C;EFyZ9C;EKxYU;IHjBV,gBAA8C;EF4Z9C;EK3YU;IHjBV,uBAA8C;EF+Z9C;EK9YU;IHjBV,uBAA8C;EFka9C;EKjZU;IHjBV,gBAA8C;EFqa9C;EKpZU;IHjBV,uBAA8C;EFwa9C;EKvZU;IHjBV,uBAA8C;EF2a9C;AACF;;AGvaI;EE3BE;IACE,0BAAa;IAAb,aAAa;IACb,oBAAY;IAAZ,YAAY;IACZ,YAAY;IACZ,eAAe;ELscrB;EKjcQ;IHuBN,kBAAuB;IAAvB,cAAuB;IACvB,eAAwB;EF6a1B;EKrcQ;IHuBN,iBAAuB;IAAvB,aAAuB;IACvB,cAAwB;EFib1B;EKzcQ;IHuBN,wBAAuB;IAAvB,oBAAuB;IACvB,qBAAwB;EFqb1B;EK7cQ;IHuBN,iBAAuB;IAAvB,aAAuB;IACvB,cAAwB;EFyb1B;EKjdQ;IHuBN,iBAAuB;IAAvB,aAAuB;IACvB,cAAwB;EF6b1B;EKrdQ;IHuBN,wBAAuB;IAAvB,oBAAuB;IACvB,qBAAwB;EFic1B;EKndI;IHAJ,kBAAc;IAAd,cAAc;IACd,WAAW;IACX,eAAe;EFsdf;EKldQ;IHdR,uBAAsC;IAAtC,mBAAsC;IAItC,oBAAuC;EFgevC;EKtdQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFoevC;EK1dQ;IHdR,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EFwevC;EK9dQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EF4evC;EKleQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFgfvC;EKteQ;IHdR,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EFofvC;EK1eQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFwfvC;EK9eQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EF4fvC;EKlfQ;IHdR,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EFggBvC;EKtfQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFogBvC;EK1fQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFwgBvC;EK9fQ;IHdR,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;EF4gBvC;EK5fI;IAAwB,kBAAS;IAAT,SAAS;EL+frC;EK7fI;IAAuB,kBDuKG;ICvKH,SDuKG;EJyV9B;EK7fM;IAAwB,iBADZ;IACY,QADZ;ELigBlB;EKhgBM;IAAwB,iBADZ;IACY,QADZ;ELogBlB;EKngBM;IAAwB,iBADZ;IACY,QADZ;ELugBlB;EKtgBM;IAAwB,iBADZ;IACY,QADZ;EL0gBlB;EKzgBM;IAAwB,iBADZ;IACY,QADZ;EL6gBlB;EK5gBM;IAAwB,iBADZ;IACY,QADZ;ELghBlB;EK/gBM;IAAwB,iBADZ;IACY,QADZ;ELmhBlB;EKlhBM;IAAwB,iBADZ;IACY,QADZ;ELshBlB;EKrhBM;IAAwB,iBADZ;IACY,QADZ;ELyhBlB;EKxhBM;IAAwB,iBADZ;IACY,QADZ;EL4hBlB;EK3hBM;IAAwB,kBADZ;IACY,SADZ;EL+hBlB;EK9hBM;IAAwB,kBADZ;IACY,SADZ;ELkiBlB;EKjiBM;IAAwB,kBADZ;IACY,SADZ;ELqiBlB;EK7hBU;IHjBV,cAA4B;EFijB5B;EKhiBU;IHjBV,sBAA8C;EFojB9C;EKniBU;IHjBV,uBAA8C;EFujB9C;EKtiBU;IHjBV,gBAA8C;EF0jB9C;EKziBU;IHjBV,uBAA8C;EF6jB9C;EK5iBU;IHjBV,uBAA8C;EFgkB9C;EK/iBU;IHjBV,gBAA8C;EFmkB9C;EKljBU;IHjBV,uBAA8C;EFskB9C;EKrjBU;IHjBV,uBAA8C;EFykB9C;EKxjBU;IHjBV,gBAA8C;EF4kB9C;EK3jBU;IHjBV,uBAA8C;EF+kB9C;EK9jBU;IHjBV,uBAA8C;EFklB9C;AACF;;AG9kBI;EE3BE;IACE,0BAAa;IAAb,aAAa;IACb,oBAAY;IAAZ,YAAY;IACZ,YAAY;IACZ,eAAe;EL6mBrB;EKxmBQ;IHuBN,kBAAuB;IAAvB,cAAuB;IACvB,eAAwB;EFolB1B;EK5mBQ;IHuBN,iBAAuB;IAAvB,aAAuB;IACvB,cAAwB;EFwlB1B;EKhnBQ;IHuBN,wBAAuB;IAAvB,oBAAuB;IACvB,qBAAwB;EF4lB1B;EKpnBQ;IHuBN,iBAAuB;IAAvB,aAAuB;IACvB,cAAwB;EFgmB1B;EKxnBQ;IHuBN,iBAAuB;IAAvB,aAAuB;IACvB,cAAwB;EFomB1B;EK5nBQ;IHuBN,wBAAuB;IAAvB,oBAAuB;IACvB,qBAAwB;EFwmB1B;EK1nBI;IHAJ,kBAAc;IAAd,cAAc;IACd,WAAW;IACX,eAAe;EF6nBf;EKznBQ;IHdR,uBAAsC;IAAtC,mBAAsC;IAItC,oBAAuC;EFuoBvC;EK7nBQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EF2oBvC;EKjoBQ;IHdR,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EF+oBvC;EKroBQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFmpBvC;EKzoBQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFupBvC;EK7oBQ;IHdR,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EF2pBvC;EKjpBQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EF+pBvC;EKrpBQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFmqBvC;EKzpBQ;IHdR,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EFuqBvC;EK7pBQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EF2qBvC;EKjqBQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EF+qBvC;EKrqBQ;IHdR,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;EFmrBvC;EKnqBI;IAAwB,kBAAS;IAAT,SAAS;ELsqBrC;EKpqBI;IAAuB,kBDuKG;ICvKH,SDuKG;EJggB9B;EKpqBM;IAAwB,iBADZ;IACY,QADZ;ELwqBlB;EKvqBM;IAAwB,iBADZ;IACY,QADZ;EL2qBlB;EK1qBM;IAAwB,iBADZ;IACY,QADZ;EL8qBlB;EK7qBM;IAAwB,iBADZ;IACY,QADZ;ELirBlB;EKhrBM;IAAwB,iBADZ;IACY,QADZ;ELorBlB;EKnrBM;IAAwB,iBADZ;IACY,QADZ;ELurBlB;EKtrBM;IAAwB,iBADZ;IACY,QADZ;EL0rBlB;EKzrBM;IAAwB,iBADZ;IACY,QADZ;EL6rBlB;EK5rBM;IAAwB,iBADZ;IACY,QADZ;ELgsBlB;EK/rBM;IAAwB,iBADZ;IACY,QADZ;ELmsBlB;EKlsBM;IAAwB,kBADZ;IACY,SADZ;ELssBlB;EKrsBM;IAAwB,kBADZ;IACY,SADZ;ELysBlB;EKxsBM;IAAwB,kBADZ;IACY,SADZ;EL4sBlB;EKpsBU;IHjBV,cAA4B;EFwtB5B;EKvsBU;IHjBV,sBAA8C;EF2tB9C;EK1sBU;IHjBV,uBAA8C;EF8tB9C;EK7sBU;IHjBV,gBAA8C;EFiuB9C;EKhtBU;IHjBV,uBAA8C;EFouB9C;EKntBU;IHjBV,uBAA8C;EFuuB9C;EKttBU;IHjBV,gBAA8C;EF0uB9C;EKztBU;IHjBV,uBAA8C;EF6uB9C;EK5tBU;IHjBV,uBAA8C;EFgvB9C;EK/tBU;IHjBV,gBAA8C;EFmvB9C;EKluBU;IHjBV,uBAA8C;EFsvB9C;EKruBU;IHjBV,uBAA8C;EFyvB9C;AACF;;AGrvBI;EE3BE;IACE,0BAAa;IAAb,aAAa;IACb,oBAAY;IAAZ,YAAY;IACZ,YAAY;IACZ,eAAe;ELoxBrB;EK/wBQ;IHuBN,kBAAuB;IAAvB,cAAuB;IACvB,eAAwB;EF2vB1B;EKnxBQ;IHuBN,iBAAuB;IAAvB,aAAuB;IACvB,cAAwB;EF+vB1B;EKvxBQ;IHuBN,wBAAuB;IAAvB,oBAAuB;IACvB,qBAAwB;EFmwB1B;EK3xBQ;IHuBN,iBAAuB;IAAvB,aAAuB;IACvB,cAAwB;EFuwB1B;EK/xBQ;IHuBN,iBAAuB;IAAvB,aAAuB;IACvB,cAAwB;EF2wB1B;EKnyBQ;IHuBN,wBAAuB;IAAvB,oBAAuB;IACvB,qBAAwB;EF+wB1B;EKjyBI;IHAJ,kBAAc;IAAd,cAAc;IACd,WAAW;IACX,eAAe;EFoyBf;EKhyBQ;IHdR,uBAAsC;IAAtC,mBAAsC;IAItC,oBAAuC;EF8yBvC;EKpyBQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFkzBvC;EKxyBQ;IHdR,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EFszBvC;EK5yBQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EF0zBvC;EKhzBQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EF8zBvC;EKpzBQ;IHdR,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EFk0BvC;EKxzBQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFs0BvC;EK5zBQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EF00BvC;EKh0BQ;IHdR,iBAAsC;IAAtC,aAAsC;IAItC,cAAuC;EF80BvC;EKp0BQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFk1BvC;EKx0BQ;IHdR,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;EFs1BvC;EK50BQ;IHdR,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;EF01BvC;EK10BI;IAAwB,kBAAS;IAAT,SAAS;EL60BrC;EK30BI;IAAuB,kBDuKG;ICvKH,SDuKG;EJuqB9B;EK30BM;IAAwB,iBADZ;IACY,QADZ;EL+0BlB;EK90BM;IAAwB,iBADZ;IACY,QADZ;ELk1BlB;EKj1BM;IAAwB,iBADZ;IACY,QADZ;ELq1BlB;EKp1BM;IAAwB,iBADZ;IACY,QADZ;ELw1BlB;EKv1BM;IAAwB,iBADZ;IACY,QADZ;EL21BlB;EK11BM;IAAwB,iBADZ;IACY,QADZ;EL81BlB;EK71BM;IAAwB,iBADZ;IACY,QADZ;ELi2BlB;EKh2BM;IAAwB,iBADZ;IACY,QADZ;ELo2BlB;EKn2BM;IAAwB,iBADZ;IACY,QADZ;ELu2BlB;EKt2BM;IAAwB,iBADZ;IACY,QADZ;EL02BlB;EKz2BM;IAAwB,kBADZ;IACY,SADZ;EL62BlB;EK52BM;IAAwB,kBADZ;IACY,SADZ;ELg3BlB;EK/2BM;IAAwB,kBADZ;IACY,SADZ;ELm3BlB;EK32BU;IHjBV,cAA4B;EF+3B5B;EK92BU;IHjBV,sBAA8C;EFk4B9C;EKj3BU;IHjBV,uBAA8C;EFq4B9C;EKp3BU;IHjBV,gBAA8C;EFw4B9C;EKv3BU;IHjBV,uBAA8C;EF24B9C;EK13BU;IHjBV,uBAA8C;EF84B9C;EK73BU;IHjBV,gBAA8C;EFi5B9C;EKh4BU;IHjBV,uBAA8C;EFo5B9C;EKn4BU;IHjBV,uBAA8C;EFu5B9C;EKt4BU;IHjBV,gBAA8C;EF05B9C;EKz4BU;IHjBV,uBAA8C;EF65B9C;EK54BU;IHjBV,uBAA8C;EFg6B9C;AACF;;AM78BM;EAAwB,wBAA0B;ANi9BxD;;AMj9BM;EAAwB,0BAA0B;ANq9BxD;;AMr9BM;EAAwB,gCAA0B;ANy9BxD;;AMz9BM;EAAwB,yBAA0B;AN69BxD;;AM79BM;EAAwB,yBAA0B;ANi+BxD;;AMj+BM;EAAwB,6BAA0B;ANq+BxD;;AMr+BM;EAAwB,8BAA0B;ANy+BxD;;AMz+BM;EAAwB,+BAA0B;EAA1B,wBAA0B;AN6+BxD;;AM7+BM;EAAwB,sCAA0B;EAA1B,+BAA0B;ANi/BxD;;AGh8BI;EGjDE;IAAwB,wBAA0B;ENs/BtD;EMt/BI;IAAwB,0BAA0B;ENy/BtD;EMz/BI;IAAwB,gCAA0B;EN4/BtD;EM5/BI;IAAwB,yBAA0B;EN+/BtD;EM//BI;IAAwB,yBAA0B;ENkgCtD;EMlgCI;IAAwB,6BAA0B;ENqgCtD;EMrgCI;IAAwB,8BAA0B;ENwgCtD;EMxgCI;IAAwB,+BAA0B;IAA1B,wBAA0B;EN2gCtD;EM3gCI;IAAwB,sCAA0B;IAA1B,+BAA0B;EN8gCtD;AACF;;AG99BI;EGjDE;IAAwB,wBAA0B;ENohCtD;EMphCI;IAAwB,0BAA0B;ENuhCtD;EMvhCI;IAAwB,gCAA0B;EN0hCtD;EM1hCI;IAAwB,yBAA0B;EN6hCtD;EM7hCI;IAAwB,yBAA0B;ENgiCtD;EMhiCI;IAAwB,6BAA0B;ENmiCtD;EMniCI;IAAwB,8BAA0B;ENsiCtD;EMtiCI;IAAwB,+BAA0B;IAA1B,wBAA0B;ENyiCtD;EMziCI;IAAwB,sCAA0B;IAA1B,+BAA0B;EN4iCtD;AACF;;AG5/BI;EGjDE;IAAwB,wBAA0B;ENkjCtD;EMljCI;IAAwB,0BAA0B;ENqjCtD;EMrjCI;IAAwB,gCAA0B;ENwjCtD;EMxjCI;IAAwB,yBAA0B;EN2jCtD;EM3jCI;IAAwB,yBAA0B;EN8jCtD;EM9jCI;IAAwB,6BAA0B;ENikCtD;EMjkCI;IAAwB,8BAA0B;ENokCtD;EMpkCI;IAAwB,+BAA0B;IAA1B,wBAA0B;ENukCtD;EMvkCI;IAAwB,sCAA0B;IAA1B,+BAA0B;EN0kCtD;AACF;;AG1hCI;EGjDE;IAAwB,wBAA0B;ENglCtD;EMhlCI;IAAwB,0BAA0B;ENmlCtD;EMnlCI;IAAwB,gCAA0B;ENslCtD;EMtlCI;IAAwB,yBAA0B;ENylCtD;EMzlCI;IAAwB,yBAA0B;EN4lCtD;EM5lCI;IAAwB,6BAA0B;EN+lCtD;EM/lCI;IAAwB,8BAA0B;ENkmCtD;EMlmCI;IAAwB,+BAA0B;IAA1B,wBAA0B;ENqmCtD;EMrmCI;IAAwB,sCAA0B;IAA1B,+BAA0B;ENwmCtD;AACF;;AM/lCA;EAEI;IAAqB,wBAA0B;ENkmCjD;EMlmCE;IAAqB,0BAA0B;ENqmCjD;EMrmCE;IAAqB,gCAA0B;ENwmCjD;EMxmCE;IAAqB,yBAA0B;EN2mCjD;EM3mCE;IAAqB,yBAA0B;EN8mCjD;EM9mCE;IAAqB,6BAA0B;ENinCjD;EMjnCE;IAAqB,8BAA0B;ENonCjD;EMpnCE;IAAqB,+BAA0B;IAA1B,wBAA0B;ENunCjD;EMvnCE;IAAqB,sCAA0B;IAA1B,+BAA0B;EN0nCjD;AACF;;AOxoCI;EAAgC,kCAA8B;EAA9B,8BAA8B;AP4oClE;;AO3oCI;EAAgC,qCAAiC;EAAjC,iCAAiC;AP+oCrE;;AO9oCI;EAAgC,0CAAsC;EAAtC,sCAAsC;APkpC1E;;AOjpCI;EAAgC,6CAAyC;EAAzC,yCAAyC;APqpC7E;;AOnpCI;EAA8B,8BAA0B;EAA1B,0BAA0B;APupC5D;;AOtpCI;EAA8B,gCAA4B;EAA5B,4BAA4B;AP0pC9D;;AOzpCI;EAA8B,sCAAkC;EAAlC,kCAAkC;AP6pCpE;;AO5pCI;EAA8B,6BAAyB;EAAzB,yBAAyB;APgqC3D;;AO/pCI;EAA8B,+BAAuB;EAAvB,uBAAuB;APmqCzD;;AOlqCI;EAA8B,+BAAuB;EAAvB,uBAAuB;APsqCzD;;AOrqCI;EAA8B,+BAAyB;EAAzB,yBAAyB;APyqC3D;;AOxqCI;EAA8B,+BAAyB;EAAzB,yBAAyB;AP4qC3D;;AO1qCI;EAAoC,+BAAsC;EAAtC,sCAAsC;AP8qC9E;;AO7qCI;EAAoC,6BAAoC;EAApC,oCAAoC;APirC5E;;AOhrCI;EAAoC,gCAAkC;EAAlC,kCAAkC;APorC1E;;AOnrCI;EAAoC,iCAAyC;EAAzC,yCAAyC;APurCjF;;AOtrCI;EAAoC,oCAAwC;EAAxC,wCAAwC;AP0rChF;;AOxrCI;EAAiC,gCAAkC;EAAlC,kCAAkC;AP4rCvE;;AO3rCI;EAAiC,8BAAgC;EAAhC,gCAAgC;AP+rCrE;;AO9rCI;EAAiC,iCAA8B;EAA9B,8BAA8B;APksCnE;;AOjsCI;EAAiC,mCAAgC;EAAhC,gCAAgC;APqsCrE;;AOpsCI;EAAiC,kCAA+B;EAA/B,+BAA+B;APwsCpE;;AOtsCI;EAAkC,oCAAoC;EAApC,oCAAoC;AP0sC1E;;AOzsCI;EAAkC,kCAAkC;EAAlC,kCAAkC;AP6sCxE;;AO5sCI;EAAkC,qCAAgC;EAAhC,gCAAgC;APgtCtE;;AO/sCI;EAAkC,sCAAuC;EAAvC,uCAAuC;APmtC7E;;AOltCI;EAAkC,yCAAsC;EAAtC,sCAAsC;APstC5E;;AOrtCI;EAAkC,sCAAiC;EAAjC,iCAAiC;APytCvE;;AOvtCI;EAAgC,oCAA2B;EAA3B,2BAA2B;AP2tC/D;;AO1tCI;EAAgC,qCAAiC;EAAjC,iCAAiC;AP8tCrE;;AO7tCI;EAAgC,mCAA+B;EAA/B,+BAA+B;APiuCnE;;AOhuCI;EAAgC,sCAA6B;EAA7B,6BAA6B;APouCjE;;AOnuCI;EAAgC,wCAA+B;EAA/B,+BAA+B;APuuCnE;;AOtuCI;EAAgC,uCAA8B;EAA9B,8BAA8B;AP0uClE;;AG9tCI;EIlDA;IAAgC,kCAA8B;IAA9B,8BAA8B;EPqxChE;EOpxCE;IAAgC,qCAAiC;IAAjC,iCAAiC;EPuxCnE;EOtxCE;IAAgC,0CAAsC;IAAtC,sCAAsC;EPyxCxE;EOxxCE;IAAgC,6CAAyC;IAAzC,yCAAyC;EP2xC3E;EOzxCE;IAA8B,8BAA0B;IAA1B,0BAA0B;EP4xC1D;EO3xCE;IAA8B,gCAA4B;IAA5B,4BAA4B;EP8xC5D;EO7xCE;IAA8B,sCAAkC;IAAlC,kCAAkC;EPgyClE;EO/xCE;IAA8B,6BAAyB;IAAzB,yBAAyB;EPkyCzD;EOjyCE;IAA8B,+BAAuB;IAAvB,uBAAuB;EPoyCvD;EOnyCE;IAA8B,+BAAuB;IAAvB,uBAAuB;EPsyCvD;EOryCE;IAA8B,+BAAyB;IAAzB,yBAAyB;EPwyCzD;EOvyCE;IAA8B,+BAAyB;IAAzB,yBAAyB;EP0yCzD;EOxyCE;IAAoC,+BAAsC;IAAtC,sCAAsC;EP2yC5E;EO1yCE;IAAoC,6BAAoC;IAApC,oCAAoC;EP6yC1E;EO5yCE;IAAoC,gCAAkC;IAAlC,kCAAkC;EP+yCxE;EO9yCE;IAAoC,iCAAyC;IAAzC,yCAAyC;EPizC/E;EOhzCE;IAAoC,oCAAwC;IAAxC,wCAAwC;EPmzC9E;EOjzCE;IAAiC,gCAAkC;IAAlC,kCAAkC;EPozCrE;EOnzCE;IAAiC,8BAAgC;IAAhC,gCAAgC;EPszCnE;EOrzCE;IAAiC,iCAA8B;IAA9B,8BAA8B;EPwzCjE;EOvzCE;IAAiC,mCAAgC;IAAhC,gCAAgC;EP0zCnE;EOzzCE;IAAiC,kCAA+B;IAA/B,+BAA+B;EP4zClE;EO1zCE;IAAkC,oCAAoC;IAApC,oCAAoC;EP6zCxE;EO5zCE;IAAkC,kCAAkC;IAAlC,kCAAkC;EP+zCtE;EO9zCE;IAAkC,qCAAgC;IAAhC,gCAAgC;EPi0CpE;EOh0CE;IAAkC,sCAAuC;IAAvC,uCAAuC;EPm0C3E;EOl0CE;IAAkC,yCAAsC;IAAtC,sCAAsC;EPq0C1E;EOp0CE;IAAkC,sCAAiC;IAAjC,iCAAiC;EPu0CrE;EOr0CE;IAAgC,oCAA2B;IAA3B,2BAA2B;EPw0C7D;EOv0CE;IAAgC,qCAAiC;IAAjC,iCAAiC;EP00CnE;EOz0CE;IAAgC,mCAA+B;IAA/B,+BAA+B;EP40CjE;EO30CE;IAAgC,sCAA6B;IAA7B,6BAA6B;EP80C/D;EO70CE;IAAgC,wCAA+B;IAA/B,+BAA+B;EPg1CjE;EO/0CE;IAAgC,uCAA8B;IAA9B,8BAA8B;EPk1ChE;AACF;;AGv0CI;EIlDA;IAAgC,kCAA8B;IAA9B,8BAA8B;EP83ChE;EO73CE;IAAgC,qCAAiC;IAAjC,iCAAiC;EPg4CnE;EO/3CE;IAAgC,0CAAsC;IAAtC,sCAAsC;EPk4CxE;EOj4CE;IAAgC,6CAAyC;IAAzC,yCAAyC;EPo4C3E;EOl4CE;IAA8B,8BAA0B;IAA1B,0BAA0B;EPq4C1D;EOp4CE;IAA8B,gCAA4B;IAA5B,4BAA4B;EPu4C5D;EOt4CE;IAA8B,sCAAkC;IAAlC,kCAAkC;EPy4ClE;EOx4CE;IAA8B,6BAAyB;IAAzB,yBAAyB;EP24CzD;EO14CE;IAA8B,+BAAuB;IAAvB,uBAAuB;EP64CvD;EO54CE;IAA8B,+BAAuB;IAAvB,uBAAuB;EP+4CvD;EO94CE;IAA8B,+BAAyB;IAAzB,yBAAyB;EPi5CzD;EOh5CE;IAA8B,+BAAyB;IAAzB,yBAAyB;EPm5CzD;EOj5CE;IAAoC,+BAAsC;IAAtC,sCAAsC;EPo5C5E;EOn5CE;IAAoC,6BAAoC;IAApC,oCAAoC;EPs5C1E;EOr5CE;IAAoC,gCAAkC;IAAlC,kCAAkC;EPw5CxE;EOv5CE;IAAoC,iCAAyC;IAAzC,yCAAyC;EP05C/E;EOz5CE;IAAoC,oCAAwC;IAAxC,wCAAwC;EP45C9E;EO15CE;IAAiC,gCAAkC;IAAlC,kCAAkC;EP65CrE;EO55CE;IAAiC,8BAAgC;IAAhC,gCAAgC;EP+5CnE;EO95CE;IAAiC,iCAA8B;IAA9B,8BAA8B;EPi6CjE;EOh6CE;IAAiC,mCAAgC;IAAhC,gCAAgC;EPm6CnE;EOl6CE;IAAiC,kCAA+B;IAA/B,+BAA+B;EPq6ClE;EOn6CE;IAAkC,oCAAoC;IAApC,oCAAoC;EPs6CxE;EOr6CE;IAAkC,kCAAkC;IAAlC,kCAAkC;EPw6CtE;EOv6CE;IAAkC,qCAAgC;IAAhC,gCAAgC;EP06CpE;EOz6CE;IAAkC,sCAAuC;IAAvC,uCAAuC;EP46C3E;EO36CE;IAAkC,yCAAsC;IAAtC,sCAAsC;EP86C1E;EO76CE;IAAkC,sCAAiC;IAAjC,iCAAiC;EPg7CrE;EO96CE;IAAgC,oCAA2B;IAA3B,2BAA2B;EPi7C7D;EOh7CE;IAAgC,qCAAiC;IAAjC,iCAAiC;EPm7CnE;EOl7CE;IAAgC,mCAA+B;IAA/B,+BAA+B;EPq7CjE;EOp7CE;IAAgC,sCAA6B;IAA7B,6BAA6B;EPu7C/D;EOt7CE;IAAgC,wCAA+B;IAA/B,+BAA+B;EPy7CjE;EOx7CE;IAAgC,uCAA8B;IAA9B,8BAA8B;EP27ChE;AACF;;AGh7CI;EIlDA;IAAgC,kCAA8B;IAA9B,8BAA8B;EPu+ChE;EOt+CE;IAAgC,qCAAiC;IAAjC,iCAAiC;EPy+CnE;EOx+CE;IAAgC,0CAAsC;IAAtC,sCAAsC;EP2+CxE;EO1+CE;IAAgC,6CAAyC;IAAzC,yCAAyC;EP6+C3E;EO3+CE;IAA8B,8BAA0B;IAA1B,0BAA0B;EP8+C1D;EO7+CE;IAA8B,gCAA4B;IAA5B,4BAA4B;EPg/C5D;EO/+CE;IAA8B,sCAAkC;IAAlC,kCAAkC;EPk/ClE;EOj/CE;IAA8B,6BAAyB;IAAzB,yBAAyB;EPo/CzD;EOn/CE;IAA8B,+BAAuB;IAAvB,uBAAuB;EPs/CvD;EOr/CE;IAA8B,+BAAuB;IAAvB,uBAAuB;EPw/CvD;EOv/CE;IAA8B,+BAAyB;IAAzB,yBAAyB;EP0/CzD;EOz/CE;IAA8B,+BAAyB;IAAzB,yBAAyB;EP4/CzD;EO1/CE;IAAoC,+BAAsC;IAAtC,sCAAsC;EP6/C5E;EO5/CE;IAAoC,6BAAoC;IAApC,oCAAoC;EP+/C1E;EO9/CE;IAAoC,gCAAkC;IAAlC,kCAAkC;EPigDxE;EOhgDE;IAAoC,iCAAyC;IAAzC,yCAAyC;EPmgD/E;EOlgDE;IAAoC,oCAAwC;IAAxC,wCAAwC;EPqgD9E;EOngDE;IAAiC,gCAAkC;IAAlC,kCAAkC;EPsgDrE;EOrgDE;IAAiC,8BAAgC;IAAhC,gCAAgC;EPwgDnE;EOvgDE;IAAiC,iCAA8B;IAA9B,8BAA8B;EP0gDjE;EOzgDE;IAAiC,mCAAgC;IAAhC,gCAAgC;EP4gDnE;EO3gDE;IAAiC,kCAA+B;IAA/B,+BAA+B;EP8gDlE;EO5gDE;IAAkC,oCAAoC;IAApC,oCAAoC;EP+gDxE;EO9gDE;IAAkC,kCAAkC;IAAlC,kCAAkC;EPihDtE;EOhhDE;IAAkC,qCAAgC;IAAhC,gCAAgC;EPmhDpE;EOlhDE;IAAkC,sCAAuC;IAAvC,uCAAuC;EPqhD3E;EOphDE;IAAkC,yCAAsC;IAAtC,sCAAsC;EPuhD1E;EOthDE;IAAkC,sCAAiC;IAAjC,iCAAiC;EPyhDrE;EOvhDE;IAAgC,oCAA2B;IAA3B,2BAA2B;EP0hD7D;EOzhDE;IAAgC,qCAAiC;IAAjC,iCAAiC;EP4hDnE;EO3hDE;IAAgC,mCAA+B;IAA/B,+BAA+B;EP8hDjE;EO7hDE;IAAgC,sCAA6B;IAA7B,6BAA6B;EPgiD/D;EO/hDE;IAAgC,wCAA+B;IAA/B,+BAA+B;EPkiDjE;EOjiDE;IAAgC,uCAA8B;IAA9B,8BAA8B;EPoiDhE;AACF;;AGzhDI;EIlDA;IAAgC,kCAA8B;IAA9B,8BAA8B;EPglDhE;EO/kDE;IAAgC,qCAAiC;IAAjC,iCAAiC;EPklDnE;EOjlDE;IAAgC,0CAAsC;IAAtC,sCAAsC;EPolDxE;EOnlDE;IAAgC,6CAAyC;IAAzC,yCAAyC;EPslD3E;EOplDE;IAA8B,8BAA0B;IAA1B,0BAA0B;EPulD1D;EOtlDE;IAA8B,gCAA4B;IAA5B,4BAA4B;EPylD5D;EOxlDE;IAA8B,sCAAkC;IAAlC,kCAAkC;EP2lDlE;EO1lDE;IAA8B,6BAAyB;IAAzB,yBAAyB;EP6lDzD;EO5lDE;IAA8B,+BAAuB;IAAvB,uBAAuB;EP+lDvD;EO9lDE;IAA8B,+BAAuB;IAAvB,uBAAuB;EPimDvD;EOhmDE;IAA8B,+BAAyB;IAAzB,yBAAyB;EPmmDzD;EOlmDE;IAA8B,+BAAyB;IAAzB,yBAAyB;EPqmDzD;EOnmDE;IAAoC,+BAAsC;IAAtC,sCAAsC;EPsmD5E;EOrmDE;IAAoC,6BAAoC;IAApC,oCAAoC;EPwmD1E;EOvmDE;IAAoC,gCAAkC;IAAlC,kCAAkC;EP0mDxE;EOzmDE;IAAoC,iCAAyC;IAAzC,yCAAyC;EP4mD/E;EO3mDE;IAAoC,oCAAwC;IAAxC,wCAAwC;EP8mD9E;EO5mDE;IAAiC,gCAAkC;IAAlC,kCAAkC;EP+mDrE;EO9mDE;IAAiC,8BAAgC;IAAhC,gCAAgC;EPinDnE;EOhnDE;IAAiC,iCAA8B;IAA9B,8BAA8B;EPmnDjE;EOlnDE;IAAiC,mCAAgC;IAAhC,gCAAgC;EPqnDnE;EOpnDE;IAAiC,kCAA+B;IAA/B,+BAA+B;EPunDlE;EOrnDE;IAAkC,oCAAoC;IAApC,oCAAoC;EPwnDxE;EOvnDE;IAAkC,kCAAkC;IAAlC,kCAAkC;EP0nDtE;EOznDE;IAAkC,qCAAgC;IAAhC,gCAAgC;EP4nDpE;EO3nDE;IAAkC,sCAAuC;IAAvC,uCAAuC;EP8nD3E;EO7nDE;IAAkC,yCAAsC;IAAtC,sCAAsC;EPgoD1E;EO/nDE;IAAkC,sCAAiC;IAAjC,iCAAiC;EPkoDrE;EOhoDE;IAAgC,oCAA2B;IAA3B,2BAA2B;EPmoD7D;EOloDE;IAAgC,qCAAiC;IAAjC,iCAAiC;EPqoDnE;EOpoDE;IAAgC,mCAA+B;IAA/B,+BAA+B;EPuoDjE;EOtoDE;IAAgC,sCAA6B;IAA7B,6BAA6B;EPyoD/D;EOxoDE;IAAgC,wCAA+B;IAA/B,+BAA+B;EP2oDjE;EO1oDE;IAAgC,uCAA8B;IAA9B,8BAA8B;EP6oDhE;AACF;;AQprDQ;EAAgC,oBAA4B;ARwrDpE;;AQvrDQ;;EAEE,wBAAoC;AR0rD9C;;AQxrDQ;;EAEE,0BAAwC;AR2rDlD;;AQzrDQ;;EAEE,2BAA0C;AR4rDpD;;AQ1rDQ;;EAEE,yBAAsC;AR6rDhD;;AQ5sDQ;EAAgC,0BAA4B;ARgtDpE;;AQ/sDQ;;EAEE,8BAAoC;ARktD9C;;AQhtDQ;;EAEE,gCAAwC;ARmtDlD;;AQjtDQ;;EAEE,iCAA0C;ARotDpD;;AQltDQ;;EAEE,+BAAsC;ARqtDhD;;AQpuDQ;EAAgC,yBAA4B;ARwuDpE;;AQvuDQ;;EAEE,6BAAoC;AR0uD9C;;AQxuDQ;;EAEE,+BAAwC;AR2uDlD;;AQzuDQ;;EAEE,gCAA0C;AR4uDpD;;AQ1uDQ;;EAEE,8BAAsC;AR6uDhD;;AQ5vDQ;EAAgC,uBAA4B;ARgwDpE;;AQ/vDQ;;EAEE,2BAAoC;ARkwD9C;;AQhwDQ;;EAEE,6BAAwC;ARmwDlD;;AQjwDQ;;EAEE,8BAA0C;ARowDpD;;AQlwDQ;;EAEE,4BAAsC;ARqwDhD;;AQpxDQ;EAAgC,yBAA4B;ARwxDpE;;AQvxDQ;;EAEE,6BAAoC;AR0xD9C;;AQxxDQ;;EAEE,+BAAwC;AR2xDlD;;AQzxDQ;;EAEE,gCAA0C;AR4xDpD;;AQ1xDQ;;EAEE,8BAAsC;AR6xDhD;;AQ5yDQ;EAAgC,uBAA4B;ARgzDpE;;AQ/yDQ;;EAEE,2BAAoC;ARkzD9C;;AQhzDQ;;EAEE,6BAAwC;ARmzDlD;;AQjzDQ;;EAEE,8BAA0C;ARozDpD;;AQlzDQ;;EAEE,4BAAsC;ARqzDhD;;AQp0DQ;EAAgC,qBAA4B;ARw0DpE;;AQv0DQ;;EAEE,yBAAoC;AR00D9C;;AQx0DQ;;EAEE,2BAAwC;AR20DlD;;AQz0DQ;;EAEE,4BAA0C;AR40DpD;;AQ10DQ;;EAEE,0BAAsC;AR60DhD;;AQ51DQ;EAAgC,2BAA4B;ARg2DpE;;AQ/1DQ;;EAEE,+BAAoC;ARk2D9C;;AQh2DQ;;EAEE,iCAAwC;ARm2DlD;;AQj2DQ;;EAEE,kCAA0C;ARo2DpD;;AQl2DQ;;EAEE,gCAAsC;ARq2DhD;;AQp3DQ;EAAgC,0BAA4B;ARw3DpE;;AQv3DQ;;EAEE,8BAAoC;AR03D9C;;AQx3DQ;;EAEE,gCAAwC;AR23DlD;;AQz3DQ;;EAEE,iCAA0C;AR43DpD;;AQ13DQ;;EAEE,+BAAsC;AR63DhD;;AQ54DQ;EAAgC,wBAA4B;ARg5DpE;;AQ/4DQ;;EAEE,4BAAoC;ARk5D9C;;AQh5DQ;;EAEE,8BAAwC;ARm5DlD;;AQj5DQ;;EAEE,+BAA0C;ARo5DpD;;AQl5DQ;;EAEE,6BAAsC;ARq5DhD;;AQp6DQ;EAAgC,0BAA4B;ARw6DpE;;AQv6DQ;;EAEE,8BAAoC;AR06D9C;;AQx6DQ;;EAEE,gCAAwC;AR26DlD;;AQz6DQ;;EAEE,iCAA0C;AR46DpD;;AQ16DQ;;EAEE,+BAAsC;AR66DhD;;AQ57DQ;EAAgC,wBAA4B;ARg8DpE;;AQ/7DQ;;EAEE,4BAAoC;ARk8D9C;;AQh8DQ;;EAEE,8BAAwC;ARm8DlD;;AQj8DQ;;EAEE,+BAA0C;ARo8DpD;;AQl8DQ;;EAEE,6BAAsC;ARq8DhD;;AQ77DQ;EAAwB,2BAA2B;ARi8D3D;;AQh8DQ;;EAEE,+BAA+B;ARm8DzC;;AQj8DQ;;EAEE,iCAAiC;ARo8D3C;;AQl8DQ;;EAEE,kCAAkC;ARq8D5C;;AQn8DQ;;EAEE,gCAAgC;ARs8D1C;;AQr9DQ;EAAwB,0BAA2B;ARy9D3D;;AQx9DQ;;EAEE,8BAA+B;AR29DzC;;AQz9DQ;;EAEE,gCAAiC;AR49D3C;;AQ19DQ;;EAEE,iCAAkC;AR69D5C;;AQ39DQ;;EAEE,+BAAgC;AR89D1C;;AQ7+DQ;EAAwB,wBAA2B;ARi/D3D;;AQh/DQ;;EAEE,4BAA+B;ARm/DzC;;AQj/DQ;;EAEE,8BAAiC;ARo/D3C;;AQl/DQ;;EAEE,+BAAkC;ARq/D5C;;AQn/DQ;;EAEE,6BAAgC;ARs/D1C;;AQrgEQ;EAAwB,0BAA2B;ARygE3D;;AQxgEQ;;EAEE,8BAA+B;AR2gEzC;;AQzgEQ;;EAEE,gCAAiC;AR4gE3C;;AQ1gEQ;;EAEE,iCAAkC;AR6gE5C;;AQ3gEQ;;EAEE,+BAAgC;AR8gE1C;;AQ7hEQ;EAAwB,wBAA2B;ARiiE3D;;AQhiEQ;;EAEE,4BAA+B;ARmiEzC;;AQjiEQ;;EAEE,8BAAiC;ARoiE3C;;AQliEQ;;EAEE,+BAAkC;ARqiE5C;;AQniEQ;;EAEE,6BAAgC;ARsiE1C;;AQhiEI;EAAmB,uBAAuB;ARoiE9C;;AQniEI;;EAEE,2BAA2B;ARsiEjC;;AQpiEI;;EAEE,6BAA6B;ARuiEnC;;AQriEI;;EAEE,8BAA8B;ARwiEpC;;AQtiEI;;EAEE,4BAA4B;ARyiElC;;AGljEI;EKlDI;IAAgC,oBAA4B;ERymElE;EQxmEM;;IAEE,wBAAoC;ER0mE5C;EQxmEM;;IAEE,0BAAwC;ER0mEhD;EQxmEM;;IAEE,2BAA0C;ER0mElD;EQxmEM;;IAEE,yBAAsC;ER0mE9C;EQznEM;IAAgC,0BAA4B;ER4nElE;EQ3nEM;;IAEE,8BAAoC;ER6nE5C;EQ3nEM;;IAEE,gCAAwC;ER6nEhD;EQ3nEM;;IAEE,iCAA0C;ER6nElD;EQ3nEM;;IAEE,+BAAsC;ER6nE9C;EQ5oEM;IAAgC,yBAA4B;ER+oElE;EQ9oEM;;IAEE,6BAAoC;ERgpE5C;EQ9oEM;;IAEE,+BAAwC;ERgpEhD;EQ9oEM;;IAEE,gCAA0C;ERgpElD;EQ9oEM;;IAEE,8BAAsC;ERgpE9C;EQ/pEM;IAAgC,uBAA4B;ERkqElE;EQjqEM;;IAEE,2BAAoC;ERmqE5C;EQjqEM;;IAEE,6BAAwC;ERmqEhD;EQjqEM;;IAEE,8BAA0C;ERmqElD;EQjqEM;;IAEE,4BAAsC;ERmqE9C;EQlrEM;IAAgC,yBAA4B;ERqrElE;EQprEM;;IAEE,6BAAoC;ERsrE5C;EQprEM;;IAEE,+BAAwC;ERsrEhD;EQprEM;;IAEE,gCAA0C;ERsrElD;EQprEM;;IAEE,8BAAsC;ERsrE9C;EQrsEM;IAAgC,uBAA4B;ERwsElE;EQvsEM;;IAEE,2BAAoC;ERysE5C;EQvsEM;;IAEE,6BAAwC;ERysEhD;EQvsEM;;IAEE,8BAA0C;ERysElD;EQvsEM;;IAEE,4BAAsC;ERysE9C;EQxtEM;IAAgC,qBAA4B;ER2tElE;EQ1tEM;;IAEE,yBAAoC;ER4tE5C;EQ1tEM;;IAEE,2BAAwC;ER4tEhD;EQ1tEM;;IAEE,4BAA0C;ER4tElD;EQ1tEM;;IAEE,0BAAsC;ER4tE9C;EQ3uEM;IAAgC,2BAA4B;ER8uElE;EQ7uEM;;IAEE,+BAAoC;ER+uE5C;EQ7uEM;;IAEE,iCAAwC;ER+uEhD;EQ7uEM;;IAEE,kCAA0C;ER+uElD;EQ7uEM;;IAEE,gCAAsC;ER+uE9C;EQ9vEM;IAAgC,0BAA4B;ERiwElE;EQhwEM;;IAEE,8BAAoC;ERkwE5C;EQhwEM;;IAEE,gCAAwC;ERkwEhD;EQhwEM;;IAEE,iCAA0C;ERkwElD;EQhwEM;;IAEE,+BAAsC;ERkwE9C;EQjxEM;IAAgC,wBAA4B;ERoxElE;EQnxEM;;IAEE,4BAAoC;ERqxE5C;EQnxEM;;IAEE,8BAAwC;ERqxEhD;EQnxEM;;IAEE,+BAA0C;ERqxElD;EQnxEM;;IAEE,6BAAsC;ERqxE9C;EQpyEM;IAAgC,0BAA4B;ERuyElE;EQtyEM;;IAEE,8BAAoC;ERwyE5C;EQtyEM;;IAEE,gCAAwC;ERwyEhD;EQtyEM;;IAEE,iCAA0C;ERwyElD;EQtyEM;;IAEE,+BAAsC;ERwyE9C;EQvzEM;IAAgC,wBAA4B;ER0zElE;EQzzEM;;IAEE,4BAAoC;ER2zE5C;EQzzEM;;IAEE,8BAAwC;ER2zEhD;EQzzEM;;IAEE,+BAA0C;ER2zElD;EQzzEM;;IAEE,6BAAsC;ER2zE9C;EQnzEM;IAAwB,2BAA2B;ERszEzD;EQrzEM;;IAEE,+BAA+B;ERuzEvC;EQrzEM;;IAEE,iCAAiC;ERuzEzC;EQrzEM;;IAEE,kCAAkC;ERuzE1C;EQrzEM;;IAEE,gCAAgC;ERuzExC;EQt0EM;IAAwB,0BAA2B;ERy0EzD;EQx0EM;;IAEE,8BAA+B;ER00EvC;EQx0EM;;IAEE,gCAAiC;ER00EzC;EQx0EM;;IAEE,iCAAkC;ER00E1C;EQx0EM;;IAEE,+BAAgC;ER00ExC;EQz1EM;IAAwB,wBAA2B;ER41EzD;EQ31EM;;IAEE,4BAA+B;ER61EvC;EQ31EM;;IAEE,8BAAiC;ER61EzC;EQ31EM;;IAEE,+BAAkC;ER61E1C;EQ31EM;;IAEE,6BAAgC;ER61ExC;EQ52EM;IAAwB,0BAA2B;ER+2EzD;EQ92EM;;IAEE,8BAA+B;ERg3EvC;EQ92EM;;IAEE,gCAAiC;ERg3EzC;EQ92EM;;IAEE,iCAAkC;ERg3E1C;EQ92EM;;IAEE,+BAAgC;ERg3ExC;EQ/3EM;IAAwB,wBAA2B;ERk4EzD;EQj4EM;;IAEE,4BAA+B;ERm4EvC;EQj4EM;;IAEE,8BAAiC;ERm4EzC;EQj4EM;;IAEE,+BAAkC;ERm4E1C;EQj4EM;;IAEE,6BAAgC;ERm4ExC;EQ73EE;IAAmB,uBAAuB;ERg4E5C;EQ/3EE;;IAEE,2BAA2B;ERi4E/B;EQ/3EE;;IAEE,6BAA6B;ERi4EjC;EQ/3EE;;IAEE,8BAA8B;ERi4ElC;EQ/3EE;;IAEE,4BAA4B;ERi4EhC;AACF;;AG34EI;EKlDI;IAAgC,oBAA4B;ERk8ElE;EQj8EM;;IAEE,wBAAoC;ERm8E5C;EQj8EM;;IAEE,0BAAwC;ERm8EhD;EQj8EM;;IAEE,2BAA0C;ERm8ElD;EQj8EM;;IAEE,yBAAsC;ERm8E9C;EQl9EM;IAAgC,0BAA4B;ERq9ElE;EQp9EM;;IAEE,8BAAoC;ERs9E5C;EQp9EM;;IAEE,gCAAwC;ERs9EhD;EQp9EM;;IAEE,iCAA0C;ERs9ElD;EQp9EM;;IAEE,+BAAsC;ERs9E9C;EQr+EM;IAAgC,yBAA4B;ERw+ElE;EQv+EM;;IAEE,6BAAoC;ERy+E5C;EQv+EM;;IAEE,+BAAwC;ERy+EhD;EQv+EM;;IAEE,gCAA0C;ERy+ElD;EQv+EM;;IAEE,8BAAsC;ERy+E9C;EQx/EM;IAAgC,uBAA4B;ER2/ElE;EQ1/EM;;IAEE,2BAAoC;ER4/E5C;EQ1/EM;;IAEE,6BAAwC;ER4/EhD;EQ1/EM;;IAEE,8BAA0C;ER4/ElD;EQ1/EM;;IAEE,4BAAsC;ER4/E9C;EQ3gFM;IAAgC,yBAA4B;ER8gFlE;EQ7gFM;;IAEE,6BAAoC;ER+gF5C;EQ7gFM;;IAEE,+BAAwC;ER+gFhD;EQ7gFM;;IAEE,gCAA0C;ER+gFlD;EQ7gFM;;IAEE,8BAAsC;ER+gF9C;EQ9hFM;IAAgC,uBAA4B;ERiiFlE;EQhiFM;;IAEE,2BAAoC;ERkiF5C;EQhiFM;;IAEE,6BAAwC;ERkiFhD;EQhiFM;;IAEE,8BAA0C;ERkiFlD;EQhiFM;;IAEE,4BAAsC;ERkiF9C;EQjjFM;IAAgC,qBAA4B;ERojFlE;EQnjFM;;IAEE,yBAAoC;ERqjF5C;EQnjFM;;IAEE,2BAAwC;ERqjFhD;EQnjFM;;IAEE,4BAA0C;ERqjFlD;EQnjFM;;IAEE,0BAAsC;ERqjF9C;EQpkFM;IAAgC,2BAA4B;ERukFlE;EQtkFM;;IAEE,+BAAoC;ERwkF5C;EQtkFM;;IAEE,iCAAwC;ERwkFhD;EQtkFM;;IAEE,kCAA0C;ERwkFlD;EQtkFM;;IAEE,gCAAsC;ERwkF9C;EQvlFM;IAAgC,0BAA4B;ER0lFlE;EQzlFM;;IAEE,8BAAoC;ER2lF5C;EQzlFM;;IAEE,gCAAwC;ER2lFhD;EQzlFM;;IAEE,iCAA0C;ER2lFlD;EQzlFM;;IAEE,+BAAsC;ER2lF9C;EQ1mFM;IAAgC,wBAA4B;ER6mFlE;EQ5mFM;;IAEE,4BAAoC;ER8mF5C;EQ5mFM;;IAEE,8BAAwC;ER8mFhD;EQ5mFM;;IAEE,+BAA0C;ER8mFlD;EQ5mFM;;IAEE,6BAAsC;ER8mF9C;EQ7nFM;IAAgC,0BAA4B;ERgoFlE;EQ/nFM;;IAEE,8BAAoC;ERioF5C;EQ/nFM;;IAEE,gCAAwC;ERioFhD;EQ/nFM;;IAEE,iCAA0C;ERioFlD;EQ/nFM;;IAEE,+BAAsC;ERioF9C;EQhpFM;IAAgC,wBAA4B;ERmpFlE;EQlpFM;;IAEE,4BAAoC;ERopF5C;EQlpFM;;IAEE,8BAAwC;ERopFhD;EQlpFM;;IAEE,+BAA0C;ERopFlD;EQlpFM;;IAEE,6BAAsC;ERopF9C;EQ5oFM;IAAwB,2BAA2B;ER+oFzD;EQ9oFM;;IAEE,+BAA+B;ERgpFvC;EQ9oFM;;IAEE,iCAAiC;ERgpFzC;EQ9oFM;;IAEE,kCAAkC;ERgpF1C;EQ9oFM;;IAEE,gCAAgC;ERgpFxC;EQ/pFM;IAAwB,0BAA2B;ERkqFzD;EQjqFM;;IAEE,8BAA+B;ERmqFvC;EQjqFM;;IAEE,gCAAiC;ERmqFzC;EQjqFM;;IAEE,iCAAkC;ERmqF1C;EQjqFM;;IAEE,+BAAgC;ERmqFxC;EQlrFM;IAAwB,wBAA2B;ERqrFzD;EQprFM;;IAEE,4BAA+B;ERsrFvC;EQprFM;;IAEE,8BAAiC;ERsrFzC;EQprFM;;IAEE,+BAAkC;ERsrF1C;EQprFM;;IAEE,6BAAgC;ERsrFxC;EQrsFM;IAAwB,0BAA2B;ERwsFzD;EQvsFM;;IAEE,8BAA+B;ERysFvC;EQvsFM;;IAEE,gCAAiC;ERysFzC;EQvsFM;;IAEE,iCAAkC;ERysF1C;EQvsFM;;IAEE,+BAAgC;ERysFxC;EQxtFM;IAAwB,wBAA2B;ER2tFzD;EQ1tFM;;IAEE,4BAA+B;ER4tFvC;EQ1tFM;;IAEE,8BAAiC;ER4tFzC;EQ1tFM;;IAEE,+BAAkC;ER4tF1C;EQ1tFM;;IAEE,6BAAgC;ER4tFxC;EQttFE;IAAmB,uBAAuB;ERytF5C;EQxtFE;;IAEE,2BAA2B;ER0tF/B;EQxtFE;;IAEE,6BAA6B;ER0tFjC;EQxtFE;;IAEE,8BAA8B;ER0tFlC;EQxtFE;;IAEE,4BAA4B;ER0tFhC;AACF;;AGpuFI;EKlDI;IAAgC,oBAA4B;ER2xFlE;EQ1xFM;;IAEE,wBAAoC;ER4xF5C;EQ1xFM;;IAEE,0BAAwC;ER4xFhD;EQ1xFM;;IAEE,2BAA0C;ER4xFlD;EQ1xFM;;IAEE,yBAAsC;ER4xF9C;EQ3yFM;IAAgC,0BAA4B;ER8yFlE;EQ7yFM;;IAEE,8BAAoC;ER+yF5C;EQ7yFM;;IAEE,gCAAwC;ER+yFhD;EQ7yFM;;IAEE,iCAA0C;ER+yFlD;EQ7yFM;;IAEE,+BAAsC;ER+yF9C;EQ9zFM;IAAgC,yBAA4B;ERi0FlE;EQh0FM;;IAEE,6BAAoC;ERk0F5C;EQh0FM;;IAEE,+BAAwC;ERk0FhD;EQh0FM;;IAEE,gCAA0C;ERk0FlD;EQh0FM;;IAEE,8BAAsC;ERk0F9C;EQj1FM;IAAgC,uBAA4B;ERo1FlE;EQn1FM;;IAEE,2BAAoC;ERq1F5C;EQn1FM;;IAEE,6BAAwC;ERq1FhD;EQn1FM;;IAEE,8BAA0C;ERq1FlD;EQn1FM;;IAEE,4BAAsC;ERq1F9C;EQp2FM;IAAgC,yBAA4B;ERu2FlE;EQt2FM;;IAEE,6BAAoC;ERw2F5C;EQt2FM;;IAEE,+BAAwC;ERw2FhD;EQt2FM;;IAEE,gCAA0C;ERw2FlD;EQt2FM;;IAEE,8BAAsC;ERw2F9C;EQv3FM;IAAgC,uBAA4B;ER03FlE;EQz3FM;;IAEE,2BAAoC;ER23F5C;EQz3FM;;IAEE,6BAAwC;ER23FhD;EQz3FM;;IAEE,8BAA0C;ER23FlD;EQz3FM;;IAEE,4BAAsC;ER23F9C;EQ14FM;IAAgC,qBAA4B;ER64FlE;EQ54FM;;IAEE,yBAAoC;ER84F5C;EQ54FM;;IAEE,2BAAwC;ER84FhD;EQ54FM;;IAEE,4BAA0C;ER84FlD;EQ54FM;;IAEE,0BAAsC;ER84F9C;EQ75FM;IAAgC,2BAA4B;ERg6FlE;EQ/5FM;;IAEE,+BAAoC;ERi6F5C;EQ/5FM;;IAEE,iCAAwC;ERi6FhD;EQ/5FM;;IAEE,kCAA0C;ERi6FlD;EQ/5FM;;IAEE,gCAAsC;ERi6F9C;EQh7FM;IAAgC,0BAA4B;ERm7FlE;EQl7FM;;IAEE,8BAAoC;ERo7F5C;EQl7FM;;IAEE,gCAAwC;ERo7FhD;EQl7FM;;IAEE,iCAA0C;ERo7FlD;EQl7FM;;IAEE,+BAAsC;ERo7F9C;EQn8FM;IAAgC,wBAA4B;ERs8FlE;EQr8FM;;IAEE,4BAAoC;ERu8F5C;EQr8FM;;IAEE,8BAAwC;ERu8FhD;EQr8FM;;IAEE,+BAA0C;ERu8FlD;EQr8FM;;IAEE,6BAAsC;ERu8F9C;EQt9FM;IAAgC,0BAA4B;ERy9FlE;EQx9FM;;IAEE,8BAAoC;ER09F5C;EQx9FM;;IAEE,gCAAwC;ER09FhD;EQx9FM;;IAEE,iCAA0C;ER09FlD;EQx9FM;;IAEE,+BAAsC;ER09F9C;EQz+FM;IAAgC,wBAA4B;ER4+FlE;EQ3+FM;;IAEE,4BAAoC;ER6+F5C;EQ3+FM;;IAEE,8BAAwC;ER6+FhD;EQ3+FM;;IAEE,+BAA0C;ER6+FlD;EQ3+FM;;IAEE,6BAAsC;ER6+F9C;EQr+FM;IAAwB,2BAA2B;ERw+FzD;EQv+FM;;IAEE,+BAA+B;ERy+FvC;EQv+FM;;IAEE,iCAAiC;ERy+FzC;EQv+FM;;IAEE,kCAAkC;ERy+F1C;EQv+FM;;IAEE,gCAAgC;ERy+FxC;EQx/FM;IAAwB,0BAA2B;ER2/FzD;EQ1/FM;;IAEE,8BAA+B;ER4/FvC;EQ1/FM;;IAEE,gCAAiC;ER4/FzC;EQ1/FM;;IAEE,iCAAkC;ER4/F1C;EQ1/FM;;IAEE,+BAAgC;ER4/FxC;EQ3gGM;IAAwB,wBAA2B;ER8gGzD;EQ7gGM;;IAEE,4BAA+B;ER+gGvC;EQ7gGM;;IAEE,8BAAiC;ER+gGzC;EQ7gGM;;IAEE,+BAAkC;ER+gG1C;EQ7gGM;;IAEE,6BAAgC;ER+gGxC;EQ9hGM;IAAwB,0BAA2B;ERiiGzD;EQhiGM;;IAEE,8BAA+B;ERkiGvC;EQhiGM;;IAEE,gCAAiC;ERkiGzC;EQhiGM;;IAEE,iCAAkC;ERkiG1C;EQhiGM;;IAEE,+BAAgC;ERkiGxC;EQjjGM;IAAwB,wBAA2B;ERojGzD;EQnjGM;;IAEE,4BAA+B;ERqjGvC;EQnjGM;;IAEE,8BAAiC;ERqjGzC;EQnjGM;;IAEE,+BAAkC;ERqjG1C;EQnjGM;;IAEE,6BAAgC;ERqjGxC;EQ/iGE;IAAmB,uBAAuB;ERkjG5C;EQjjGE;;IAEE,2BAA2B;ERmjG/B;EQjjGE;;IAEE,6BAA6B;ERmjGjC;EQjjGE;;IAEE,8BAA8B;ERmjGlC;EQjjGE;;IAEE,4BAA4B;ERmjGhC;AACF;;AG7jGI;EKlDI;IAAgC,oBAA4B;ERonGlE;EQnnGM;;IAEE,wBAAoC;ERqnG5C;EQnnGM;;IAEE,0BAAwC;ERqnGhD;EQnnGM;;IAEE,2BAA0C;ERqnGlD;EQnnGM;;IAEE,yBAAsC;ERqnG9C;EQpoGM;IAAgC,0BAA4B;ERuoGlE;EQtoGM;;IAEE,8BAAoC;ERwoG5C;EQtoGM;;IAEE,gCAAwC;ERwoGhD;EQtoGM;;IAEE,iCAA0C;ERwoGlD;EQtoGM;;IAEE,+BAAsC;ERwoG9C;EQvpGM;IAAgC,yBAA4B;ER0pGlE;EQzpGM;;IAEE,6BAAoC;ER2pG5C;EQzpGM;;IAEE,+BAAwC;ER2pGhD;EQzpGM;;IAEE,gCAA0C;ER2pGlD;EQzpGM;;IAEE,8BAAsC;ER2pG9C;EQ1qGM;IAAgC,uBAA4B;ER6qGlE;EQ5qGM;;IAEE,2BAAoC;ER8qG5C;EQ5qGM;;IAEE,6BAAwC;ER8qGhD;EQ5qGM;;IAEE,8BAA0C;ER8qGlD;EQ5qGM;;IAEE,4BAAsC;ER8qG9C;EQ7rGM;IAAgC,yBAA4B;ERgsGlE;EQ/rGM;;IAEE,6BAAoC;ERisG5C;EQ/rGM;;IAEE,+BAAwC;ERisGhD;EQ/rGM;;IAEE,gCAA0C;ERisGlD;EQ/rGM;;IAEE,8BAAsC;ERisG9C;EQhtGM;IAAgC,uBAA4B;ERmtGlE;EQltGM;;IAEE,2BAAoC;ERotG5C;EQltGM;;IAEE,6BAAwC;ERotGhD;EQltGM;;IAEE,8BAA0C;ERotGlD;EQltGM;;IAEE,4BAAsC;ERotG9C;EQnuGM;IAAgC,qBAA4B;ERsuGlE;EQruGM;;IAEE,yBAAoC;ERuuG5C;EQruGM;;IAEE,2BAAwC;ERuuGhD;EQruGM;;IAEE,4BAA0C;ERuuGlD;EQruGM;;IAEE,0BAAsC;ERuuG9C;EQtvGM;IAAgC,2BAA4B;ERyvGlE;EQxvGM;;IAEE,+BAAoC;ER0vG5C;EQxvGM;;IAEE,iCAAwC;ER0vGhD;EQxvGM;;IAEE,kCAA0C;ER0vGlD;EQxvGM;;IAEE,gCAAsC;ER0vG9C;EQzwGM;IAAgC,0BAA4B;ER4wGlE;EQ3wGM;;IAEE,8BAAoC;ER6wG5C;EQ3wGM;;IAEE,gCAAwC;ER6wGhD;EQ3wGM;;IAEE,iCAA0C;ER6wGlD;EQ3wGM;;IAEE,+BAAsC;ER6wG9C;EQ5xGM;IAAgC,wBAA4B;ER+xGlE;EQ9xGM;;IAEE,4BAAoC;ERgyG5C;EQ9xGM;;IAEE,8BAAwC;ERgyGhD;EQ9xGM;;IAEE,+BAA0C;ERgyGlD;EQ9xGM;;IAEE,6BAAsC;ERgyG9C;EQ/yGM;IAAgC,0BAA4B;ERkzGlE;EQjzGM;;IAEE,8BAAoC;ERmzG5C;EQjzGM;;IAEE,gCAAwC;ERmzGhD;EQjzGM;;IAEE,iCAA0C;ERmzGlD;EQjzGM;;IAEE,+BAAsC;ERmzG9C;EQl0GM;IAAgC,wBAA4B;ERq0GlE;EQp0GM;;IAEE,4BAAoC;ERs0G5C;EQp0GM;;IAEE,8BAAwC;ERs0GhD;EQp0GM;;IAEE,+BAA0C;ERs0GlD;EQp0GM;;IAEE,6BAAsC;ERs0G9C;EQ9zGM;IAAwB,2BAA2B;ERi0GzD;EQh0GM;;IAEE,+BAA+B;ERk0GvC;EQh0GM;;IAEE,iCAAiC;ERk0GzC;EQh0GM;;IAEE,kCAAkC;ERk0G1C;EQh0GM;;IAEE,gCAAgC;ERk0GxC;EQj1GM;IAAwB,0BAA2B;ERo1GzD;EQn1GM;;IAEE,8BAA+B;ERq1GvC;EQn1GM;;IAEE,gCAAiC;ERq1GzC;EQn1GM;;IAEE,iCAAkC;ERq1G1C;EQn1GM;;IAEE,+BAAgC;ERq1GxC;EQp2GM;IAAwB,wBAA2B;ERu2GzD;EQt2GM;;IAEE,4BAA+B;ERw2GvC;EQt2GM;;IAEE,8BAAiC;ERw2GzC;EQt2GM;;IAEE,+BAAkC;ERw2G1C;EQt2GM;;IAEE,6BAAgC;ERw2GxC;EQv3GM;IAAwB,0BAA2B;ER03GzD;EQz3GM;;IAEE,8BAA+B;ER23GvC;EQz3GM;;IAEE,gCAAiC;ER23GzC;EQz3GM;;IAEE,iCAAkC;ER23G1C;EQz3GM;;IAEE,+BAAgC;ER23GxC;EQ14GM;IAAwB,wBAA2B;ER64GzD;EQ54GM;;IAEE,4BAA+B;ER84GvC;EQ54GM;;IAEE,8BAAiC;ER84GzC;EQ54GM;;IAEE,+BAAkC;ER84G1C;EQ54GM;;IAEE,6BAAgC;ER84GxC;EQx4GE;IAAmB,uBAAuB;ER24G5C;EQ14GE;;IAEE,2BAA2B;ER44G/B;EQ14GE;;IAEE,6BAA6B;ER44GjC;EQ14GE;;IAEE,8BAA8B;ER44GlC;EQ14GE;;IAEE,4BAA4B;ER44GhC;AACF","file":"bootstrap-grid.css","sourcesContent":["/*!\n * Bootstrap Grid v4.5.0 (https://getbootstrap.com/)\n * Copyright 2011-2020 The Bootstrap Authors\n * Copyright 2011-2020 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\nhtml {\n box-sizing: border-box;\n -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n@import \"functions\";\n@import \"variables\";\n\n@import \"mixins/breakpoints\";\n@import \"mixins/grid-framework\";\n@import \"mixins/grid\";\n\n@import \"grid\";\n@import \"utilities/display\";\n@import \"utilities/flex\";\n@import \"utilities/spacing\";\n","/*!\n * Bootstrap Grid v4.5.0 (https://getbootstrap.com/)\n * Copyright 2011-2020 The Bootstrap Authors\n * Copyright 2011-2020 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\nhtml {\n box-sizing: border-box;\n -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n.container {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n@media (min-width: 576px) {\n .container {\n max-width: 540px;\n }\n}\n\n@media (min-width: 768px) {\n .container {\n max-width: 720px;\n }\n}\n\n@media (min-width: 992px) {\n .container {\n max-width: 960px;\n }\n}\n\n@media (min-width: 1200px) {\n .container {\n max-width: 1140px;\n }\n}\n\n.container-fluid, .container-sm, .container-md, .container-lg, .container-xl {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n@media (min-width: 576px) {\n .container, .container-sm {\n max-width: 540px;\n }\n}\n\n@media (min-width: 768px) {\n .container, .container-sm, .container-md {\n max-width: 720px;\n }\n}\n\n@media (min-width: 992px) {\n .container, .container-sm, .container-md, .container-lg {\n max-width: 960px;\n }\n}\n\n@media (min-width: 1200px) {\n .container, .container-sm, .container-md, .container-lg, .container-xl {\n max-width: 1140px;\n }\n}\n\n.row {\n display: flex;\n flex-wrap: wrap;\n margin-right: -15px;\n margin-left: -15px;\n}\n\n.no-gutters {\n margin-right: 0;\n margin-left: 0;\n}\n\n.no-gutters > .col,\n.no-gutters > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n}\n\n.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col,\n.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,\n.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,\n.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,\n.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,\n.col-xl-auto {\n position: relative;\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n}\n\n.col {\n flex-basis: 0;\n flex-grow: 1;\n min-width: 0;\n max-width: 100%;\n}\n\n.row-cols-1 > * {\n flex: 0 0 100%;\n max-width: 100%;\n}\n\n.row-cols-2 > * {\n flex: 0 0 50%;\n max-width: 50%;\n}\n\n.row-cols-3 > * {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n}\n\n.row-cols-4 > * {\n flex: 0 0 25%;\n max-width: 25%;\n}\n\n.row-cols-5 > * {\n flex: 0 0 20%;\n max-width: 20%;\n}\n\n.row-cols-6 > * {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n}\n\n.col-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n}\n\n.col-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n}\n\n.col-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n}\n\n.col-3 {\n flex: 0 0 25%;\n max-width: 25%;\n}\n\n.col-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n}\n\n.col-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n}\n\n.col-6 {\n flex: 0 0 50%;\n max-width: 50%;\n}\n\n.col-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n}\n\n.col-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n}\n\n.col-9 {\n flex: 0 0 75%;\n max-width: 75%;\n}\n\n.col-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n}\n\n.col-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n}\n\n.col-12 {\n flex: 0 0 100%;\n max-width: 100%;\n}\n\n.order-first {\n order: -1;\n}\n\n.order-last {\n order: 13;\n}\n\n.order-0 {\n order: 0;\n}\n\n.order-1 {\n order: 1;\n}\n\n.order-2 {\n order: 2;\n}\n\n.order-3 {\n order: 3;\n}\n\n.order-4 {\n order: 4;\n}\n\n.order-5 {\n order: 5;\n}\n\n.order-6 {\n order: 6;\n}\n\n.order-7 {\n order: 7;\n}\n\n.order-8 {\n order: 8;\n}\n\n.order-9 {\n order: 9;\n}\n\n.order-10 {\n order: 10;\n}\n\n.order-11 {\n order: 11;\n}\n\n.order-12 {\n order: 12;\n}\n\n.offset-1 {\n margin-left: 8.333333%;\n}\n\n.offset-2 {\n margin-left: 16.666667%;\n}\n\n.offset-3 {\n margin-left: 25%;\n}\n\n.offset-4 {\n margin-left: 33.333333%;\n}\n\n.offset-5 {\n margin-left: 41.666667%;\n}\n\n.offset-6 {\n margin-left: 50%;\n}\n\n.offset-7 {\n margin-left: 58.333333%;\n}\n\n.offset-8 {\n margin-left: 66.666667%;\n}\n\n.offset-9 {\n margin-left: 75%;\n}\n\n.offset-10 {\n margin-left: 83.333333%;\n}\n\n.offset-11 {\n margin-left: 91.666667%;\n}\n\n@media (min-width: 576px) {\n .col-sm {\n flex-basis: 0;\n flex-grow: 1;\n min-width: 0;\n max-width: 100%;\n }\n .row-cols-sm-1 > * {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .row-cols-sm-2 > * {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .row-cols-sm-3 > * {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .row-cols-sm-4 > * {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .row-cols-sm-5 > * {\n flex: 0 0 20%;\n max-width: 20%;\n }\n .row-cols-sm-6 > * {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-sm-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-sm-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-sm-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-sm-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-sm-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-sm-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-sm-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-sm-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-sm-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-sm-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-sm-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-sm-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-sm-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-sm-first {\n order: -1;\n }\n .order-sm-last {\n order: 13;\n }\n .order-sm-0 {\n order: 0;\n }\n .order-sm-1 {\n order: 1;\n }\n .order-sm-2 {\n order: 2;\n }\n .order-sm-3 {\n order: 3;\n }\n .order-sm-4 {\n order: 4;\n }\n .order-sm-5 {\n order: 5;\n }\n .order-sm-6 {\n order: 6;\n }\n .order-sm-7 {\n order: 7;\n }\n .order-sm-8 {\n order: 8;\n }\n .order-sm-9 {\n order: 9;\n }\n .order-sm-10 {\n order: 10;\n }\n .order-sm-11 {\n order: 11;\n }\n .order-sm-12 {\n order: 12;\n }\n .offset-sm-0 {\n margin-left: 0;\n }\n .offset-sm-1 {\n margin-left: 8.333333%;\n }\n .offset-sm-2 {\n margin-left: 16.666667%;\n }\n .offset-sm-3 {\n margin-left: 25%;\n }\n .offset-sm-4 {\n margin-left: 33.333333%;\n }\n .offset-sm-5 {\n margin-left: 41.666667%;\n }\n .offset-sm-6 {\n margin-left: 50%;\n }\n .offset-sm-7 {\n margin-left: 58.333333%;\n }\n .offset-sm-8 {\n margin-left: 66.666667%;\n }\n .offset-sm-9 {\n margin-left: 75%;\n }\n .offset-sm-10 {\n margin-left: 83.333333%;\n }\n .offset-sm-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 768px) {\n .col-md {\n flex-basis: 0;\n flex-grow: 1;\n min-width: 0;\n max-width: 100%;\n }\n .row-cols-md-1 > * {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .row-cols-md-2 > * {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .row-cols-md-3 > * {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .row-cols-md-4 > * {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .row-cols-md-5 > * {\n flex: 0 0 20%;\n max-width: 20%;\n }\n .row-cols-md-6 > * {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-md-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-md-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-md-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-md-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-md-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-md-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-md-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-md-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-md-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-md-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-md-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-md-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-md-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-md-first {\n order: -1;\n }\n .order-md-last {\n order: 13;\n }\n .order-md-0 {\n order: 0;\n }\n .order-md-1 {\n order: 1;\n }\n .order-md-2 {\n order: 2;\n }\n .order-md-3 {\n order: 3;\n }\n .order-md-4 {\n order: 4;\n }\n .order-md-5 {\n order: 5;\n }\n .order-md-6 {\n order: 6;\n }\n .order-md-7 {\n order: 7;\n }\n .order-md-8 {\n order: 8;\n }\n .order-md-9 {\n order: 9;\n }\n .order-md-10 {\n order: 10;\n }\n .order-md-11 {\n order: 11;\n }\n .order-md-12 {\n order: 12;\n }\n .offset-md-0 {\n margin-left: 0;\n }\n .offset-md-1 {\n margin-left: 8.333333%;\n }\n .offset-md-2 {\n margin-left: 16.666667%;\n }\n .offset-md-3 {\n margin-left: 25%;\n }\n .offset-md-4 {\n margin-left: 33.333333%;\n }\n .offset-md-5 {\n margin-left: 41.666667%;\n }\n .offset-md-6 {\n margin-left: 50%;\n }\n .offset-md-7 {\n margin-left: 58.333333%;\n }\n .offset-md-8 {\n margin-left: 66.666667%;\n }\n .offset-md-9 {\n margin-left: 75%;\n }\n .offset-md-10 {\n margin-left: 83.333333%;\n }\n .offset-md-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 992px) {\n .col-lg {\n flex-basis: 0;\n flex-grow: 1;\n min-width: 0;\n max-width: 100%;\n }\n .row-cols-lg-1 > * {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .row-cols-lg-2 > * {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .row-cols-lg-3 > * {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .row-cols-lg-4 > * {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .row-cols-lg-5 > * {\n flex: 0 0 20%;\n max-width: 20%;\n }\n .row-cols-lg-6 > * {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-lg-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-lg-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-lg-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-lg-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-lg-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-lg-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-lg-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-lg-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-lg-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-lg-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-lg-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-lg-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-lg-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-lg-first {\n order: -1;\n }\n .order-lg-last {\n order: 13;\n }\n .order-lg-0 {\n order: 0;\n }\n .order-lg-1 {\n order: 1;\n }\n .order-lg-2 {\n order: 2;\n }\n .order-lg-3 {\n order: 3;\n }\n .order-lg-4 {\n order: 4;\n }\n .order-lg-5 {\n order: 5;\n }\n .order-lg-6 {\n order: 6;\n }\n .order-lg-7 {\n order: 7;\n }\n .order-lg-8 {\n order: 8;\n }\n .order-lg-9 {\n order: 9;\n }\n .order-lg-10 {\n order: 10;\n }\n .order-lg-11 {\n order: 11;\n }\n .order-lg-12 {\n order: 12;\n }\n .offset-lg-0 {\n margin-left: 0;\n }\n .offset-lg-1 {\n margin-left: 8.333333%;\n }\n .offset-lg-2 {\n margin-left: 16.666667%;\n }\n .offset-lg-3 {\n margin-left: 25%;\n }\n .offset-lg-4 {\n margin-left: 33.333333%;\n }\n .offset-lg-5 {\n margin-left: 41.666667%;\n }\n .offset-lg-6 {\n margin-left: 50%;\n }\n .offset-lg-7 {\n margin-left: 58.333333%;\n }\n .offset-lg-8 {\n margin-left: 66.666667%;\n }\n .offset-lg-9 {\n margin-left: 75%;\n }\n .offset-lg-10 {\n margin-left: 83.333333%;\n }\n .offset-lg-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 1200px) {\n .col-xl {\n flex-basis: 0;\n flex-grow: 1;\n min-width: 0;\n max-width: 100%;\n }\n .row-cols-xl-1 > * {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .row-cols-xl-2 > * {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .row-cols-xl-3 > * {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .row-cols-xl-4 > * {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .row-cols-xl-5 > * {\n flex: 0 0 20%;\n max-width: 20%;\n }\n .row-cols-xl-6 > * {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-xl-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-xl-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-xl-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-xl-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-xl-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-xl-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-xl-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-xl-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-xl-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-xl-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-xl-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-xl-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-xl-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-xl-first {\n order: -1;\n }\n .order-xl-last {\n order: 13;\n }\n .order-xl-0 {\n order: 0;\n }\n .order-xl-1 {\n order: 1;\n }\n .order-xl-2 {\n order: 2;\n }\n .order-xl-3 {\n order: 3;\n }\n .order-xl-4 {\n order: 4;\n }\n .order-xl-5 {\n order: 5;\n }\n .order-xl-6 {\n order: 6;\n }\n .order-xl-7 {\n order: 7;\n }\n .order-xl-8 {\n order: 8;\n }\n .order-xl-9 {\n order: 9;\n }\n .order-xl-10 {\n order: 10;\n }\n .order-xl-11 {\n order: 11;\n }\n .order-xl-12 {\n order: 12;\n }\n .offset-xl-0 {\n margin-left: 0;\n }\n .offset-xl-1 {\n margin-left: 8.333333%;\n }\n .offset-xl-2 {\n margin-left: 16.666667%;\n }\n .offset-xl-3 {\n margin-left: 25%;\n }\n .offset-xl-4 {\n margin-left: 33.333333%;\n }\n .offset-xl-5 {\n margin-left: 41.666667%;\n }\n .offset-xl-6 {\n margin-left: 50%;\n }\n .offset-xl-7 {\n margin-left: 58.333333%;\n }\n .offset-xl-8 {\n margin-left: 66.666667%;\n }\n .offset-xl-9 {\n margin-left: 75%;\n }\n .offset-xl-10 {\n margin-left: 83.333333%;\n }\n .offset-xl-11 {\n margin-left: 91.666667%;\n }\n}\n\n.d-none {\n display: none !important;\n}\n\n.d-inline {\n display: inline !important;\n}\n\n.d-inline-block {\n display: inline-block !important;\n}\n\n.d-block {\n display: block !important;\n}\n\n.d-table {\n display: table !important;\n}\n\n.d-table-row {\n display: table-row !important;\n}\n\n.d-table-cell {\n display: table-cell !important;\n}\n\n.d-flex {\n display: flex !important;\n}\n\n.d-inline-flex {\n display: inline-flex !important;\n}\n\n@media (min-width: 576px) {\n .d-sm-none {\n display: none !important;\n }\n .d-sm-inline {\n display: inline !important;\n }\n .d-sm-inline-block {\n display: inline-block !important;\n }\n .d-sm-block {\n display: block !important;\n }\n .d-sm-table {\n display: table !important;\n }\n .d-sm-table-row {\n display: table-row !important;\n }\n .d-sm-table-cell {\n display: table-cell !important;\n }\n .d-sm-flex {\n display: flex !important;\n }\n .d-sm-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 768px) {\n .d-md-none {\n display: none !important;\n }\n .d-md-inline {\n display: inline !important;\n }\n .d-md-inline-block {\n display: inline-block !important;\n }\n .d-md-block {\n display: block !important;\n }\n .d-md-table {\n display: table !important;\n }\n .d-md-table-row {\n display: table-row !important;\n }\n .d-md-table-cell {\n display: table-cell !important;\n }\n .d-md-flex {\n display: flex !important;\n }\n .d-md-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 992px) {\n .d-lg-none {\n display: none !important;\n }\n .d-lg-inline {\n display: inline !important;\n }\n .d-lg-inline-block {\n display: inline-block !important;\n }\n .d-lg-block {\n display: block !important;\n }\n .d-lg-table {\n display: table !important;\n }\n .d-lg-table-row {\n display: table-row !important;\n }\n .d-lg-table-cell {\n display: table-cell !important;\n }\n .d-lg-flex {\n display: flex !important;\n }\n .d-lg-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 1200px) {\n .d-xl-none {\n display: none !important;\n }\n .d-xl-inline {\n display: inline !important;\n }\n .d-xl-inline-block {\n display: inline-block !important;\n }\n .d-xl-block {\n display: block !important;\n }\n .d-xl-table {\n display: table !important;\n }\n .d-xl-table-row {\n display: table-row !important;\n }\n .d-xl-table-cell {\n display: table-cell !important;\n }\n .d-xl-flex {\n display: flex !important;\n }\n .d-xl-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media print {\n .d-print-none {\n display: none !important;\n }\n .d-print-inline {\n display: inline !important;\n }\n .d-print-inline-block {\n display: inline-block !important;\n }\n .d-print-block {\n display: block !important;\n }\n .d-print-table {\n display: table !important;\n }\n .d-print-table-row {\n display: table-row !important;\n }\n .d-print-table-cell {\n display: table-cell !important;\n }\n .d-print-flex {\n display: flex !important;\n }\n .d-print-inline-flex {\n display: inline-flex !important;\n }\n}\n\n.flex-row {\n flex-direction: row !important;\n}\n\n.flex-column {\n flex-direction: column !important;\n}\n\n.flex-row-reverse {\n flex-direction: row-reverse !important;\n}\n\n.flex-column-reverse {\n flex-direction: column-reverse !important;\n}\n\n.flex-wrap {\n flex-wrap: wrap !important;\n}\n\n.flex-nowrap {\n flex-wrap: nowrap !important;\n}\n\n.flex-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n}\n\n.flex-fill {\n flex: 1 1 auto !important;\n}\n\n.flex-grow-0 {\n flex-grow: 0 !important;\n}\n\n.flex-grow-1 {\n flex-grow: 1 !important;\n}\n\n.flex-shrink-0 {\n flex-shrink: 0 !important;\n}\n\n.flex-shrink-1 {\n flex-shrink: 1 !important;\n}\n\n.justify-content-start {\n justify-content: flex-start !important;\n}\n\n.justify-content-end {\n justify-content: flex-end !important;\n}\n\n.justify-content-center {\n justify-content: center !important;\n}\n\n.justify-content-between {\n justify-content: space-between !important;\n}\n\n.justify-content-around {\n justify-content: space-around !important;\n}\n\n.align-items-start {\n align-items: flex-start !important;\n}\n\n.align-items-end {\n align-items: flex-end !important;\n}\n\n.align-items-center {\n align-items: center !important;\n}\n\n.align-items-baseline {\n align-items: baseline !important;\n}\n\n.align-items-stretch {\n align-items: stretch !important;\n}\n\n.align-content-start {\n align-content: flex-start !important;\n}\n\n.align-content-end {\n align-content: flex-end !important;\n}\n\n.align-content-center {\n align-content: center !important;\n}\n\n.align-content-between {\n align-content: space-between !important;\n}\n\n.align-content-around {\n align-content: space-around !important;\n}\n\n.align-content-stretch {\n align-content: stretch !important;\n}\n\n.align-self-auto {\n align-self: auto !important;\n}\n\n.align-self-start {\n align-self: flex-start !important;\n}\n\n.align-self-end {\n align-self: flex-end !important;\n}\n\n.align-self-center {\n align-self: center !important;\n}\n\n.align-self-baseline {\n align-self: baseline !important;\n}\n\n.align-self-stretch {\n align-self: stretch !important;\n}\n\n@media (min-width: 576px) {\n .flex-sm-row {\n flex-direction: row !important;\n }\n .flex-sm-column {\n flex-direction: column !important;\n }\n .flex-sm-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-sm-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-sm-wrap {\n flex-wrap: wrap !important;\n }\n .flex-sm-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-sm-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-sm-fill {\n flex: 1 1 auto !important;\n }\n .flex-sm-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-sm-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-sm-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-sm-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-sm-start {\n justify-content: flex-start !important;\n }\n .justify-content-sm-end {\n justify-content: flex-end !important;\n }\n .justify-content-sm-center {\n justify-content: center !important;\n }\n .justify-content-sm-between {\n justify-content: space-between !important;\n }\n .justify-content-sm-around {\n justify-content: space-around !important;\n }\n .align-items-sm-start {\n align-items: flex-start !important;\n }\n .align-items-sm-end {\n align-items: flex-end !important;\n }\n .align-items-sm-center {\n align-items: center !important;\n }\n .align-items-sm-baseline {\n align-items: baseline !important;\n }\n .align-items-sm-stretch {\n align-items: stretch !important;\n }\n .align-content-sm-start {\n align-content: flex-start !important;\n }\n .align-content-sm-end {\n align-content: flex-end !important;\n }\n .align-content-sm-center {\n align-content: center !important;\n }\n .align-content-sm-between {\n align-content: space-between !important;\n }\n .align-content-sm-around {\n align-content: space-around !important;\n }\n .align-content-sm-stretch {\n align-content: stretch !important;\n }\n .align-self-sm-auto {\n align-self: auto !important;\n }\n .align-self-sm-start {\n align-self: flex-start !important;\n }\n .align-self-sm-end {\n align-self: flex-end !important;\n }\n .align-self-sm-center {\n align-self: center !important;\n }\n .align-self-sm-baseline {\n align-self: baseline !important;\n }\n .align-self-sm-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 768px) {\n .flex-md-row {\n flex-direction: row !important;\n }\n .flex-md-column {\n flex-direction: column !important;\n }\n .flex-md-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-md-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-md-wrap {\n flex-wrap: wrap !important;\n }\n .flex-md-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-md-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-md-fill {\n flex: 1 1 auto !important;\n }\n .flex-md-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-md-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-md-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-md-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-md-start {\n justify-content: flex-start !important;\n }\n .justify-content-md-end {\n justify-content: flex-end !important;\n }\n .justify-content-md-center {\n justify-content: center !important;\n }\n .justify-content-md-between {\n justify-content: space-between !important;\n }\n .justify-content-md-around {\n justify-content: space-around !important;\n }\n .align-items-md-start {\n align-items: flex-start !important;\n }\n .align-items-md-end {\n align-items: flex-end !important;\n }\n .align-items-md-center {\n align-items: center !important;\n }\n .align-items-md-baseline {\n align-items: baseline !important;\n }\n .align-items-md-stretch {\n align-items: stretch !important;\n }\n .align-content-md-start {\n align-content: flex-start !important;\n }\n .align-content-md-end {\n align-content: flex-end !important;\n }\n .align-content-md-center {\n align-content: center !important;\n }\n .align-content-md-between {\n align-content: space-between !important;\n }\n .align-content-md-around {\n align-content: space-around !important;\n }\n .align-content-md-stretch {\n align-content: stretch !important;\n }\n .align-self-md-auto {\n align-self: auto !important;\n }\n .align-self-md-start {\n align-self: flex-start !important;\n }\n .align-self-md-end {\n align-self: flex-end !important;\n }\n .align-self-md-center {\n align-self: center !important;\n }\n .align-self-md-baseline {\n align-self: baseline !important;\n }\n .align-self-md-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 992px) {\n .flex-lg-row {\n flex-direction: row !important;\n }\n .flex-lg-column {\n flex-direction: column !important;\n }\n .flex-lg-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-lg-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-lg-wrap {\n flex-wrap: wrap !important;\n }\n .flex-lg-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-lg-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-lg-fill {\n flex: 1 1 auto !important;\n }\n .flex-lg-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-lg-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-lg-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-lg-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-lg-start {\n justify-content: flex-start !important;\n }\n .justify-content-lg-end {\n justify-content: flex-end !important;\n }\n .justify-content-lg-center {\n justify-content: center !important;\n }\n .justify-content-lg-between {\n justify-content: space-between !important;\n }\n .justify-content-lg-around {\n justify-content: space-around !important;\n }\n .align-items-lg-start {\n align-items: flex-start !important;\n }\n .align-items-lg-end {\n align-items: flex-end !important;\n }\n .align-items-lg-center {\n align-items: center !important;\n }\n .align-items-lg-baseline {\n align-items: baseline !important;\n }\n .align-items-lg-stretch {\n align-items: stretch !important;\n }\n .align-content-lg-start {\n align-content: flex-start !important;\n }\n .align-content-lg-end {\n align-content: flex-end !important;\n }\n .align-content-lg-center {\n align-content: center !important;\n }\n .align-content-lg-between {\n align-content: space-between !important;\n }\n .align-content-lg-around {\n align-content: space-around !important;\n }\n .align-content-lg-stretch {\n align-content: stretch !important;\n }\n .align-self-lg-auto {\n align-self: auto !important;\n }\n .align-self-lg-start {\n align-self: flex-start !important;\n }\n .align-self-lg-end {\n align-self: flex-end !important;\n }\n .align-self-lg-center {\n align-self: center !important;\n }\n .align-self-lg-baseline {\n align-self: baseline !important;\n }\n .align-self-lg-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 1200px) {\n .flex-xl-row {\n flex-direction: row !important;\n }\n .flex-xl-column {\n flex-direction: column !important;\n }\n .flex-xl-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-xl-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-xl-wrap {\n flex-wrap: wrap !important;\n }\n .flex-xl-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-xl-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-xl-fill {\n flex: 1 1 auto !important;\n }\n .flex-xl-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-xl-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-xl-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-xl-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-xl-start {\n justify-content: flex-start !important;\n }\n .justify-content-xl-end {\n justify-content: flex-end !important;\n }\n .justify-content-xl-center {\n justify-content: center !important;\n }\n .justify-content-xl-between {\n justify-content: space-between !important;\n }\n .justify-content-xl-around {\n justify-content: space-around !important;\n }\n .align-items-xl-start {\n align-items: flex-start !important;\n }\n .align-items-xl-end {\n align-items: flex-end !important;\n }\n .align-items-xl-center {\n align-items: center !important;\n }\n .align-items-xl-baseline {\n align-items: baseline !important;\n }\n .align-items-xl-stretch {\n align-items: stretch !important;\n }\n .align-content-xl-start {\n align-content: flex-start !important;\n }\n .align-content-xl-end {\n align-content: flex-end !important;\n }\n .align-content-xl-center {\n align-content: center !important;\n }\n .align-content-xl-between {\n align-content: space-between !important;\n }\n .align-content-xl-around {\n align-content: space-around !important;\n }\n .align-content-xl-stretch {\n align-content: stretch !important;\n }\n .align-self-xl-auto {\n align-self: auto !important;\n }\n .align-self-xl-start {\n align-self: flex-start !important;\n }\n .align-self-xl-end {\n align-self: flex-end !important;\n }\n .align-self-xl-center {\n align-self: center !important;\n }\n .align-self-xl-baseline {\n align-self: baseline !important;\n }\n .align-self-xl-stretch {\n align-self: stretch !important;\n }\n}\n\n.m-0 {\n margin: 0 !important;\n}\n\n.mt-0,\n.my-0 {\n margin-top: 0 !important;\n}\n\n.mr-0,\n.mx-0 {\n margin-right: 0 !important;\n}\n\n.mb-0,\n.my-0 {\n margin-bottom: 0 !important;\n}\n\n.ml-0,\n.mx-0 {\n margin-left: 0 !important;\n}\n\n.m-1 {\n margin: 0.25rem !important;\n}\n\n.mt-1,\n.my-1 {\n margin-top: 0.25rem !important;\n}\n\n.mr-1,\n.mx-1 {\n margin-right: 0.25rem !important;\n}\n\n.mb-1,\n.my-1 {\n margin-bottom: 0.25rem !important;\n}\n\n.ml-1,\n.mx-1 {\n margin-left: 0.25rem !important;\n}\n\n.m-2 {\n margin: 0.5rem !important;\n}\n\n.mt-2,\n.my-2 {\n margin-top: 0.5rem !important;\n}\n\n.mr-2,\n.mx-2 {\n margin-right: 0.5rem !important;\n}\n\n.mb-2,\n.my-2 {\n margin-bottom: 0.5rem !important;\n}\n\n.ml-2,\n.mx-2 {\n margin-left: 0.5rem !important;\n}\n\n.m-3 {\n margin: 1rem !important;\n}\n\n.mt-3,\n.my-3 {\n margin-top: 1rem !important;\n}\n\n.mr-3,\n.mx-3 {\n margin-right: 1rem !important;\n}\n\n.mb-3,\n.my-3 {\n margin-bottom: 1rem !important;\n}\n\n.ml-3,\n.mx-3 {\n margin-left: 1rem !important;\n}\n\n.m-4 {\n margin: 1.5rem !important;\n}\n\n.mt-4,\n.my-4 {\n margin-top: 1.5rem !important;\n}\n\n.mr-4,\n.mx-4 {\n margin-right: 1.5rem !important;\n}\n\n.mb-4,\n.my-4 {\n margin-bottom: 1.5rem !important;\n}\n\n.ml-4,\n.mx-4 {\n margin-left: 1.5rem !important;\n}\n\n.m-5 {\n margin: 3rem !important;\n}\n\n.mt-5,\n.my-5 {\n margin-top: 3rem !important;\n}\n\n.mr-5,\n.mx-5 {\n margin-right: 3rem !important;\n}\n\n.mb-5,\n.my-5 {\n margin-bottom: 3rem !important;\n}\n\n.ml-5,\n.mx-5 {\n margin-left: 3rem !important;\n}\n\n.p-0 {\n padding: 0 !important;\n}\n\n.pt-0,\n.py-0 {\n padding-top: 0 !important;\n}\n\n.pr-0,\n.px-0 {\n padding-right: 0 !important;\n}\n\n.pb-0,\n.py-0 {\n padding-bottom: 0 !important;\n}\n\n.pl-0,\n.px-0 {\n padding-left: 0 !important;\n}\n\n.p-1 {\n padding: 0.25rem !important;\n}\n\n.pt-1,\n.py-1 {\n padding-top: 0.25rem !important;\n}\n\n.pr-1,\n.px-1 {\n padding-right: 0.25rem !important;\n}\n\n.pb-1,\n.py-1 {\n padding-bottom: 0.25rem !important;\n}\n\n.pl-1,\n.px-1 {\n padding-left: 0.25rem !important;\n}\n\n.p-2 {\n padding: 0.5rem !important;\n}\n\n.pt-2,\n.py-2 {\n padding-top: 0.5rem !important;\n}\n\n.pr-2,\n.px-2 {\n padding-right: 0.5rem !important;\n}\n\n.pb-2,\n.py-2 {\n padding-bottom: 0.5rem !important;\n}\n\n.pl-2,\n.px-2 {\n padding-left: 0.5rem !important;\n}\n\n.p-3 {\n padding: 1rem !important;\n}\n\n.pt-3,\n.py-3 {\n padding-top: 1rem !important;\n}\n\n.pr-3,\n.px-3 {\n padding-right: 1rem !important;\n}\n\n.pb-3,\n.py-3 {\n padding-bottom: 1rem !important;\n}\n\n.pl-3,\n.px-3 {\n padding-left: 1rem !important;\n}\n\n.p-4 {\n padding: 1.5rem !important;\n}\n\n.pt-4,\n.py-4 {\n padding-top: 1.5rem !important;\n}\n\n.pr-4,\n.px-4 {\n padding-right: 1.5rem !important;\n}\n\n.pb-4,\n.py-4 {\n padding-bottom: 1.5rem !important;\n}\n\n.pl-4,\n.px-4 {\n padding-left: 1.5rem !important;\n}\n\n.p-5 {\n padding: 3rem !important;\n}\n\n.pt-5,\n.py-5 {\n padding-top: 3rem !important;\n}\n\n.pr-5,\n.px-5 {\n padding-right: 3rem !important;\n}\n\n.pb-5,\n.py-5 {\n padding-bottom: 3rem !important;\n}\n\n.pl-5,\n.px-5 {\n padding-left: 3rem !important;\n}\n\n.m-n1 {\n margin: -0.25rem !important;\n}\n\n.mt-n1,\n.my-n1 {\n margin-top: -0.25rem !important;\n}\n\n.mr-n1,\n.mx-n1 {\n margin-right: -0.25rem !important;\n}\n\n.mb-n1,\n.my-n1 {\n margin-bottom: -0.25rem !important;\n}\n\n.ml-n1,\n.mx-n1 {\n margin-left: -0.25rem !important;\n}\n\n.m-n2 {\n margin: -0.5rem !important;\n}\n\n.mt-n2,\n.my-n2 {\n margin-top: -0.5rem !important;\n}\n\n.mr-n2,\n.mx-n2 {\n margin-right: -0.5rem !important;\n}\n\n.mb-n2,\n.my-n2 {\n margin-bottom: -0.5rem !important;\n}\n\n.ml-n2,\n.mx-n2 {\n margin-left: -0.5rem !important;\n}\n\n.m-n3 {\n margin: -1rem !important;\n}\n\n.mt-n3,\n.my-n3 {\n margin-top: -1rem !important;\n}\n\n.mr-n3,\n.mx-n3 {\n margin-right: -1rem !important;\n}\n\n.mb-n3,\n.my-n3 {\n margin-bottom: -1rem !important;\n}\n\n.ml-n3,\n.mx-n3 {\n margin-left: -1rem !important;\n}\n\n.m-n4 {\n margin: -1.5rem !important;\n}\n\n.mt-n4,\n.my-n4 {\n margin-top: -1.5rem !important;\n}\n\n.mr-n4,\n.mx-n4 {\n margin-right: -1.5rem !important;\n}\n\n.mb-n4,\n.my-n4 {\n margin-bottom: -1.5rem !important;\n}\n\n.ml-n4,\n.mx-n4 {\n margin-left: -1.5rem !important;\n}\n\n.m-n5 {\n margin: -3rem !important;\n}\n\n.mt-n5,\n.my-n5 {\n margin-top: -3rem !important;\n}\n\n.mr-n5,\n.mx-n5 {\n margin-right: -3rem !important;\n}\n\n.mb-n5,\n.my-n5 {\n margin-bottom: -3rem !important;\n}\n\n.ml-n5,\n.mx-n5 {\n margin-left: -3rem !important;\n}\n\n.m-auto {\n margin: auto !important;\n}\n\n.mt-auto,\n.my-auto {\n margin-top: auto !important;\n}\n\n.mr-auto,\n.mx-auto {\n margin-right: auto !important;\n}\n\n.mb-auto,\n.my-auto {\n margin-bottom: auto !important;\n}\n\n.ml-auto,\n.mx-auto {\n margin-left: auto !important;\n}\n\n@media (min-width: 576px) {\n .m-sm-0 {\n margin: 0 !important;\n }\n .mt-sm-0,\n .my-sm-0 {\n margin-top: 0 !important;\n }\n .mr-sm-0,\n .mx-sm-0 {\n margin-right: 0 !important;\n }\n .mb-sm-0,\n .my-sm-0 {\n margin-bottom: 0 !important;\n }\n .ml-sm-0,\n .mx-sm-0 {\n margin-left: 0 !important;\n }\n .m-sm-1 {\n margin: 0.25rem !important;\n }\n .mt-sm-1,\n .my-sm-1 {\n margin-top: 0.25rem !important;\n }\n .mr-sm-1,\n .mx-sm-1 {\n margin-right: 0.25rem !important;\n }\n .mb-sm-1,\n .my-sm-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-sm-1,\n .mx-sm-1 {\n margin-left: 0.25rem !important;\n }\n .m-sm-2 {\n margin: 0.5rem !important;\n }\n .mt-sm-2,\n .my-sm-2 {\n margin-top: 0.5rem !important;\n }\n .mr-sm-2,\n .mx-sm-2 {\n margin-right: 0.5rem !important;\n }\n .mb-sm-2,\n .my-sm-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-sm-2,\n .mx-sm-2 {\n margin-left: 0.5rem !important;\n }\n .m-sm-3 {\n margin: 1rem !important;\n }\n .mt-sm-3,\n .my-sm-3 {\n margin-top: 1rem !important;\n }\n .mr-sm-3,\n .mx-sm-3 {\n margin-right: 1rem !important;\n }\n .mb-sm-3,\n .my-sm-3 {\n margin-bottom: 1rem !important;\n }\n .ml-sm-3,\n .mx-sm-3 {\n margin-left: 1rem !important;\n }\n .m-sm-4 {\n margin: 1.5rem !important;\n }\n .mt-sm-4,\n .my-sm-4 {\n margin-top: 1.5rem !important;\n }\n .mr-sm-4,\n .mx-sm-4 {\n margin-right: 1.5rem !important;\n }\n .mb-sm-4,\n .my-sm-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-sm-4,\n .mx-sm-4 {\n margin-left: 1.5rem !important;\n }\n .m-sm-5 {\n margin: 3rem !important;\n }\n .mt-sm-5,\n .my-sm-5 {\n margin-top: 3rem !important;\n }\n .mr-sm-5,\n .mx-sm-5 {\n margin-right: 3rem !important;\n }\n .mb-sm-5,\n .my-sm-5 {\n margin-bottom: 3rem !important;\n }\n .ml-sm-5,\n .mx-sm-5 {\n margin-left: 3rem !important;\n }\n .p-sm-0 {\n padding: 0 !important;\n }\n .pt-sm-0,\n .py-sm-0 {\n padding-top: 0 !important;\n }\n .pr-sm-0,\n .px-sm-0 {\n padding-right: 0 !important;\n }\n .pb-sm-0,\n .py-sm-0 {\n padding-bottom: 0 !important;\n }\n .pl-sm-0,\n .px-sm-0 {\n padding-left: 0 !important;\n }\n .p-sm-1 {\n padding: 0.25rem !important;\n }\n .pt-sm-1,\n .py-sm-1 {\n padding-top: 0.25rem !important;\n }\n .pr-sm-1,\n .px-sm-1 {\n padding-right: 0.25rem !important;\n }\n .pb-sm-1,\n .py-sm-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-sm-1,\n .px-sm-1 {\n padding-left: 0.25rem !important;\n }\n .p-sm-2 {\n padding: 0.5rem !important;\n }\n .pt-sm-2,\n .py-sm-2 {\n padding-top: 0.5rem !important;\n }\n .pr-sm-2,\n .px-sm-2 {\n padding-right: 0.5rem !important;\n }\n .pb-sm-2,\n .py-sm-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-sm-2,\n .px-sm-2 {\n padding-left: 0.5rem !important;\n }\n .p-sm-3 {\n padding: 1rem !important;\n }\n .pt-sm-3,\n .py-sm-3 {\n padding-top: 1rem !important;\n }\n .pr-sm-3,\n .px-sm-3 {\n padding-right: 1rem !important;\n }\n .pb-sm-3,\n .py-sm-3 {\n padding-bottom: 1rem !important;\n }\n .pl-sm-3,\n .px-sm-3 {\n padding-left: 1rem !important;\n }\n .p-sm-4 {\n padding: 1.5rem !important;\n }\n .pt-sm-4,\n .py-sm-4 {\n padding-top: 1.5rem !important;\n }\n .pr-sm-4,\n .px-sm-4 {\n padding-right: 1.5rem !important;\n }\n .pb-sm-4,\n .py-sm-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-sm-4,\n .px-sm-4 {\n padding-left: 1.5rem !important;\n }\n .p-sm-5 {\n padding: 3rem !important;\n }\n .pt-sm-5,\n .py-sm-5 {\n padding-top: 3rem !important;\n }\n .pr-sm-5,\n .px-sm-5 {\n padding-right: 3rem !important;\n }\n .pb-sm-5,\n .py-sm-5 {\n padding-bottom: 3rem !important;\n }\n .pl-sm-5,\n .px-sm-5 {\n padding-left: 3rem !important;\n }\n .m-sm-n1 {\n margin: -0.25rem !important;\n }\n .mt-sm-n1,\n .my-sm-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-sm-n1,\n .mx-sm-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-sm-n1,\n .my-sm-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-sm-n1,\n .mx-sm-n1 {\n margin-left: -0.25rem !important;\n }\n .m-sm-n2 {\n margin: -0.5rem !important;\n }\n .mt-sm-n2,\n .my-sm-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-sm-n2,\n .mx-sm-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-sm-n2,\n .my-sm-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-sm-n2,\n .mx-sm-n2 {\n margin-left: -0.5rem !important;\n }\n .m-sm-n3 {\n margin: -1rem !important;\n }\n .mt-sm-n3,\n .my-sm-n3 {\n margin-top: -1rem !important;\n }\n .mr-sm-n3,\n .mx-sm-n3 {\n margin-right: -1rem !important;\n }\n .mb-sm-n3,\n .my-sm-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-sm-n3,\n .mx-sm-n3 {\n margin-left: -1rem !important;\n }\n .m-sm-n4 {\n margin: -1.5rem !important;\n }\n .mt-sm-n4,\n .my-sm-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-sm-n4,\n .mx-sm-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-sm-n4,\n .my-sm-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-sm-n4,\n .mx-sm-n4 {\n margin-left: -1.5rem !important;\n }\n .m-sm-n5 {\n margin: -3rem !important;\n }\n .mt-sm-n5,\n .my-sm-n5 {\n margin-top: -3rem !important;\n }\n .mr-sm-n5,\n .mx-sm-n5 {\n margin-right: -3rem !important;\n }\n .mb-sm-n5,\n .my-sm-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-sm-n5,\n .mx-sm-n5 {\n margin-left: -3rem !important;\n }\n .m-sm-auto {\n margin: auto !important;\n }\n .mt-sm-auto,\n .my-sm-auto {\n margin-top: auto !important;\n }\n .mr-sm-auto,\n .mx-sm-auto {\n margin-right: auto !important;\n }\n .mb-sm-auto,\n .my-sm-auto {\n margin-bottom: auto !important;\n }\n .ml-sm-auto,\n .mx-sm-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 768px) {\n .m-md-0 {\n margin: 0 !important;\n }\n .mt-md-0,\n .my-md-0 {\n margin-top: 0 !important;\n }\n .mr-md-0,\n .mx-md-0 {\n margin-right: 0 !important;\n }\n .mb-md-0,\n .my-md-0 {\n margin-bottom: 0 !important;\n }\n .ml-md-0,\n .mx-md-0 {\n margin-left: 0 !important;\n }\n .m-md-1 {\n margin: 0.25rem !important;\n }\n .mt-md-1,\n .my-md-1 {\n margin-top: 0.25rem !important;\n }\n .mr-md-1,\n .mx-md-1 {\n margin-right: 0.25rem !important;\n }\n .mb-md-1,\n .my-md-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-md-1,\n .mx-md-1 {\n margin-left: 0.25rem !important;\n }\n .m-md-2 {\n margin: 0.5rem !important;\n }\n .mt-md-2,\n .my-md-2 {\n margin-top: 0.5rem !important;\n }\n .mr-md-2,\n .mx-md-2 {\n margin-right: 0.5rem !important;\n }\n .mb-md-2,\n .my-md-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-md-2,\n .mx-md-2 {\n margin-left: 0.5rem !important;\n }\n .m-md-3 {\n margin: 1rem !important;\n }\n .mt-md-3,\n .my-md-3 {\n margin-top: 1rem !important;\n }\n .mr-md-3,\n .mx-md-3 {\n margin-right: 1rem !important;\n }\n .mb-md-3,\n .my-md-3 {\n margin-bottom: 1rem !important;\n }\n .ml-md-3,\n .mx-md-3 {\n margin-left: 1rem !important;\n }\n .m-md-4 {\n margin: 1.5rem !important;\n }\n .mt-md-4,\n .my-md-4 {\n margin-top: 1.5rem !important;\n }\n .mr-md-4,\n .mx-md-4 {\n margin-right: 1.5rem !important;\n }\n .mb-md-4,\n .my-md-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-md-4,\n .mx-md-4 {\n margin-left: 1.5rem !important;\n }\n .m-md-5 {\n margin: 3rem !important;\n }\n .mt-md-5,\n .my-md-5 {\n margin-top: 3rem !important;\n }\n .mr-md-5,\n .mx-md-5 {\n margin-right: 3rem !important;\n }\n .mb-md-5,\n .my-md-5 {\n margin-bottom: 3rem !important;\n }\n .ml-md-5,\n .mx-md-5 {\n margin-left: 3rem !important;\n }\n .p-md-0 {\n padding: 0 !important;\n }\n .pt-md-0,\n .py-md-0 {\n padding-top: 0 !important;\n }\n .pr-md-0,\n .px-md-0 {\n padding-right: 0 !important;\n }\n .pb-md-0,\n .py-md-0 {\n padding-bottom: 0 !important;\n }\n .pl-md-0,\n .px-md-0 {\n padding-left: 0 !important;\n }\n .p-md-1 {\n padding: 0.25rem !important;\n }\n .pt-md-1,\n .py-md-1 {\n padding-top: 0.25rem !important;\n }\n .pr-md-1,\n .px-md-1 {\n padding-right: 0.25rem !important;\n }\n .pb-md-1,\n .py-md-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-md-1,\n .px-md-1 {\n padding-left: 0.25rem !important;\n }\n .p-md-2 {\n padding: 0.5rem !important;\n }\n .pt-md-2,\n .py-md-2 {\n padding-top: 0.5rem !important;\n }\n .pr-md-2,\n .px-md-2 {\n padding-right: 0.5rem !important;\n }\n .pb-md-2,\n .py-md-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-md-2,\n .px-md-2 {\n padding-left: 0.5rem !important;\n }\n .p-md-3 {\n padding: 1rem !important;\n }\n .pt-md-3,\n .py-md-3 {\n padding-top: 1rem !important;\n }\n .pr-md-3,\n .px-md-3 {\n padding-right: 1rem !important;\n }\n .pb-md-3,\n .py-md-3 {\n padding-bottom: 1rem !important;\n }\n .pl-md-3,\n .px-md-3 {\n padding-left: 1rem !important;\n }\n .p-md-4 {\n padding: 1.5rem !important;\n }\n .pt-md-4,\n .py-md-4 {\n padding-top: 1.5rem !important;\n }\n .pr-md-4,\n .px-md-4 {\n padding-right: 1.5rem !important;\n }\n .pb-md-4,\n .py-md-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-md-4,\n .px-md-4 {\n padding-left: 1.5rem !important;\n }\n .p-md-5 {\n padding: 3rem !important;\n }\n .pt-md-5,\n .py-md-5 {\n padding-top: 3rem !important;\n }\n .pr-md-5,\n .px-md-5 {\n padding-right: 3rem !important;\n }\n .pb-md-5,\n .py-md-5 {\n padding-bottom: 3rem !important;\n }\n .pl-md-5,\n .px-md-5 {\n padding-left: 3rem !important;\n }\n .m-md-n1 {\n margin: -0.25rem !important;\n }\n .mt-md-n1,\n .my-md-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-md-n1,\n .mx-md-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-md-n1,\n .my-md-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-md-n1,\n .mx-md-n1 {\n margin-left: -0.25rem !important;\n }\n .m-md-n2 {\n margin: -0.5rem !important;\n }\n .mt-md-n2,\n .my-md-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-md-n2,\n .mx-md-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-md-n2,\n .my-md-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-md-n2,\n .mx-md-n2 {\n margin-left: -0.5rem !important;\n }\n .m-md-n3 {\n margin: -1rem !important;\n }\n .mt-md-n3,\n .my-md-n3 {\n margin-top: -1rem !important;\n }\n .mr-md-n3,\n .mx-md-n3 {\n margin-right: -1rem !important;\n }\n .mb-md-n3,\n .my-md-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-md-n3,\n .mx-md-n3 {\n margin-left: -1rem !important;\n }\n .m-md-n4 {\n margin: -1.5rem !important;\n }\n .mt-md-n4,\n .my-md-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-md-n4,\n .mx-md-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-md-n4,\n .my-md-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-md-n4,\n .mx-md-n4 {\n margin-left: -1.5rem !important;\n }\n .m-md-n5 {\n margin: -3rem !important;\n }\n .mt-md-n5,\n .my-md-n5 {\n margin-top: -3rem !important;\n }\n .mr-md-n5,\n .mx-md-n5 {\n margin-right: -3rem !important;\n }\n .mb-md-n5,\n .my-md-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-md-n5,\n .mx-md-n5 {\n margin-left: -3rem !important;\n }\n .m-md-auto {\n margin: auto !important;\n }\n .mt-md-auto,\n .my-md-auto {\n margin-top: auto !important;\n }\n .mr-md-auto,\n .mx-md-auto {\n margin-right: auto !important;\n }\n .mb-md-auto,\n .my-md-auto {\n margin-bottom: auto !important;\n }\n .ml-md-auto,\n .mx-md-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 992px) {\n .m-lg-0 {\n margin: 0 !important;\n }\n .mt-lg-0,\n .my-lg-0 {\n margin-top: 0 !important;\n }\n .mr-lg-0,\n .mx-lg-0 {\n margin-right: 0 !important;\n }\n .mb-lg-0,\n .my-lg-0 {\n margin-bottom: 0 !important;\n }\n .ml-lg-0,\n .mx-lg-0 {\n margin-left: 0 !important;\n }\n .m-lg-1 {\n margin: 0.25rem !important;\n }\n .mt-lg-1,\n .my-lg-1 {\n margin-top: 0.25rem !important;\n }\n .mr-lg-1,\n .mx-lg-1 {\n margin-right: 0.25rem !important;\n }\n .mb-lg-1,\n .my-lg-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-lg-1,\n .mx-lg-1 {\n margin-left: 0.25rem !important;\n }\n .m-lg-2 {\n margin: 0.5rem !important;\n }\n .mt-lg-2,\n .my-lg-2 {\n margin-top: 0.5rem !important;\n }\n .mr-lg-2,\n .mx-lg-2 {\n margin-right: 0.5rem !important;\n }\n .mb-lg-2,\n .my-lg-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-lg-2,\n .mx-lg-2 {\n margin-left: 0.5rem !important;\n }\n .m-lg-3 {\n margin: 1rem !important;\n }\n .mt-lg-3,\n .my-lg-3 {\n margin-top: 1rem !important;\n }\n .mr-lg-3,\n .mx-lg-3 {\n margin-right: 1rem !important;\n }\n .mb-lg-3,\n .my-lg-3 {\n margin-bottom: 1rem !important;\n }\n .ml-lg-3,\n .mx-lg-3 {\n margin-left: 1rem !important;\n }\n .m-lg-4 {\n margin: 1.5rem !important;\n }\n .mt-lg-4,\n .my-lg-4 {\n margin-top: 1.5rem !important;\n }\n .mr-lg-4,\n .mx-lg-4 {\n margin-right: 1.5rem !important;\n }\n .mb-lg-4,\n .my-lg-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-lg-4,\n .mx-lg-4 {\n margin-left: 1.5rem !important;\n }\n .m-lg-5 {\n margin: 3rem !important;\n }\n .mt-lg-5,\n .my-lg-5 {\n margin-top: 3rem !important;\n }\n .mr-lg-5,\n .mx-lg-5 {\n margin-right: 3rem !important;\n }\n .mb-lg-5,\n .my-lg-5 {\n margin-bottom: 3rem !important;\n }\n .ml-lg-5,\n .mx-lg-5 {\n margin-left: 3rem !important;\n }\n .p-lg-0 {\n padding: 0 !important;\n }\n .pt-lg-0,\n .py-lg-0 {\n padding-top: 0 !important;\n }\n .pr-lg-0,\n .px-lg-0 {\n padding-right: 0 !important;\n }\n .pb-lg-0,\n .py-lg-0 {\n padding-bottom: 0 !important;\n }\n .pl-lg-0,\n .px-lg-0 {\n padding-left: 0 !important;\n }\n .p-lg-1 {\n padding: 0.25rem !important;\n }\n .pt-lg-1,\n .py-lg-1 {\n padding-top: 0.25rem !important;\n }\n .pr-lg-1,\n .px-lg-1 {\n padding-right: 0.25rem !important;\n }\n .pb-lg-1,\n .py-lg-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-lg-1,\n .px-lg-1 {\n padding-left: 0.25rem !important;\n }\n .p-lg-2 {\n padding: 0.5rem !important;\n }\n .pt-lg-2,\n .py-lg-2 {\n padding-top: 0.5rem !important;\n }\n .pr-lg-2,\n .px-lg-2 {\n padding-right: 0.5rem !important;\n }\n .pb-lg-2,\n .py-lg-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-lg-2,\n .px-lg-2 {\n padding-left: 0.5rem !important;\n }\n .p-lg-3 {\n padding: 1rem !important;\n }\n .pt-lg-3,\n .py-lg-3 {\n padding-top: 1rem !important;\n }\n .pr-lg-3,\n .px-lg-3 {\n padding-right: 1rem !important;\n }\n .pb-lg-3,\n .py-lg-3 {\n padding-bottom: 1rem !important;\n }\n .pl-lg-3,\n .px-lg-3 {\n padding-left: 1rem !important;\n }\n .p-lg-4 {\n padding: 1.5rem !important;\n }\n .pt-lg-4,\n .py-lg-4 {\n padding-top: 1.5rem !important;\n }\n .pr-lg-4,\n .px-lg-4 {\n padding-right: 1.5rem !important;\n }\n .pb-lg-4,\n .py-lg-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-lg-4,\n .px-lg-4 {\n padding-left: 1.5rem !important;\n }\n .p-lg-5 {\n padding: 3rem !important;\n }\n .pt-lg-5,\n .py-lg-5 {\n padding-top: 3rem !important;\n }\n .pr-lg-5,\n .px-lg-5 {\n padding-right: 3rem !important;\n }\n .pb-lg-5,\n .py-lg-5 {\n padding-bottom: 3rem !important;\n }\n .pl-lg-5,\n .px-lg-5 {\n padding-left: 3rem !important;\n }\n .m-lg-n1 {\n margin: -0.25rem !important;\n }\n .mt-lg-n1,\n .my-lg-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-lg-n1,\n .mx-lg-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-lg-n1,\n .my-lg-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-lg-n1,\n .mx-lg-n1 {\n margin-left: -0.25rem !important;\n }\n .m-lg-n2 {\n margin: -0.5rem !important;\n }\n .mt-lg-n2,\n .my-lg-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-lg-n2,\n .mx-lg-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-lg-n2,\n .my-lg-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-lg-n2,\n .mx-lg-n2 {\n margin-left: -0.5rem !important;\n }\n .m-lg-n3 {\n margin: -1rem !important;\n }\n .mt-lg-n3,\n .my-lg-n3 {\n margin-top: -1rem !important;\n }\n .mr-lg-n3,\n .mx-lg-n3 {\n margin-right: -1rem !important;\n }\n .mb-lg-n3,\n .my-lg-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-lg-n3,\n .mx-lg-n3 {\n margin-left: -1rem !important;\n }\n .m-lg-n4 {\n margin: -1.5rem !important;\n }\n .mt-lg-n4,\n .my-lg-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-lg-n4,\n .mx-lg-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-lg-n4,\n .my-lg-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-lg-n4,\n .mx-lg-n4 {\n margin-left: -1.5rem !important;\n }\n .m-lg-n5 {\n margin: -3rem !important;\n }\n .mt-lg-n5,\n .my-lg-n5 {\n margin-top: -3rem !important;\n }\n .mr-lg-n5,\n .mx-lg-n5 {\n margin-right: -3rem !important;\n }\n .mb-lg-n5,\n .my-lg-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-lg-n5,\n .mx-lg-n5 {\n margin-left: -3rem !important;\n }\n .m-lg-auto {\n margin: auto !important;\n }\n .mt-lg-auto,\n .my-lg-auto {\n margin-top: auto !important;\n }\n .mr-lg-auto,\n .mx-lg-auto {\n margin-right: auto !important;\n }\n .mb-lg-auto,\n .my-lg-auto {\n margin-bottom: auto !important;\n }\n .ml-lg-auto,\n .mx-lg-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 1200px) {\n .m-xl-0 {\n margin: 0 !important;\n }\n .mt-xl-0,\n .my-xl-0 {\n margin-top: 0 !important;\n }\n .mr-xl-0,\n .mx-xl-0 {\n margin-right: 0 !important;\n }\n .mb-xl-0,\n .my-xl-0 {\n margin-bottom: 0 !important;\n }\n .ml-xl-0,\n .mx-xl-0 {\n margin-left: 0 !important;\n }\n .m-xl-1 {\n margin: 0.25rem !important;\n }\n .mt-xl-1,\n .my-xl-1 {\n margin-top: 0.25rem !important;\n }\n .mr-xl-1,\n .mx-xl-1 {\n margin-right: 0.25rem !important;\n }\n .mb-xl-1,\n .my-xl-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-xl-1,\n .mx-xl-1 {\n margin-left: 0.25rem !important;\n }\n .m-xl-2 {\n margin: 0.5rem !important;\n }\n .mt-xl-2,\n .my-xl-2 {\n margin-top: 0.5rem !important;\n }\n .mr-xl-2,\n .mx-xl-2 {\n margin-right: 0.5rem !important;\n }\n .mb-xl-2,\n .my-xl-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-xl-2,\n .mx-xl-2 {\n margin-left: 0.5rem !important;\n }\n .m-xl-3 {\n margin: 1rem !important;\n }\n .mt-xl-3,\n .my-xl-3 {\n margin-top: 1rem !important;\n }\n .mr-xl-3,\n .mx-xl-3 {\n margin-right: 1rem !important;\n }\n .mb-xl-3,\n .my-xl-3 {\n margin-bottom: 1rem !important;\n }\n .ml-xl-3,\n .mx-xl-3 {\n margin-left: 1rem !important;\n }\n .m-xl-4 {\n margin: 1.5rem !important;\n }\n .mt-xl-4,\n .my-xl-4 {\n margin-top: 1.5rem !important;\n }\n .mr-xl-4,\n .mx-xl-4 {\n margin-right: 1.5rem !important;\n }\n .mb-xl-4,\n .my-xl-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-xl-4,\n .mx-xl-4 {\n margin-left: 1.5rem !important;\n }\n .m-xl-5 {\n margin: 3rem !important;\n }\n .mt-xl-5,\n .my-xl-5 {\n margin-top: 3rem !important;\n }\n .mr-xl-5,\n .mx-xl-5 {\n margin-right: 3rem !important;\n }\n .mb-xl-5,\n .my-xl-5 {\n margin-bottom: 3rem !important;\n }\n .ml-xl-5,\n .mx-xl-5 {\n margin-left: 3rem !important;\n }\n .p-xl-0 {\n padding: 0 !important;\n }\n .pt-xl-0,\n .py-xl-0 {\n padding-top: 0 !important;\n }\n .pr-xl-0,\n .px-xl-0 {\n padding-right: 0 !important;\n }\n .pb-xl-0,\n .py-xl-0 {\n padding-bottom: 0 !important;\n }\n .pl-xl-0,\n .px-xl-0 {\n padding-left: 0 !important;\n }\n .p-xl-1 {\n padding: 0.25rem !important;\n }\n .pt-xl-1,\n .py-xl-1 {\n padding-top: 0.25rem !important;\n }\n .pr-xl-1,\n .px-xl-1 {\n padding-right: 0.25rem !important;\n }\n .pb-xl-1,\n .py-xl-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-xl-1,\n .px-xl-1 {\n padding-left: 0.25rem !important;\n }\n .p-xl-2 {\n padding: 0.5rem !important;\n }\n .pt-xl-2,\n .py-xl-2 {\n padding-top: 0.5rem !important;\n }\n .pr-xl-2,\n .px-xl-2 {\n padding-right: 0.5rem !important;\n }\n .pb-xl-2,\n .py-xl-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-xl-2,\n .px-xl-2 {\n padding-left: 0.5rem !important;\n }\n .p-xl-3 {\n padding: 1rem !important;\n }\n .pt-xl-3,\n .py-xl-3 {\n padding-top: 1rem !important;\n }\n .pr-xl-3,\n .px-xl-3 {\n padding-right: 1rem !important;\n }\n .pb-xl-3,\n .py-xl-3 {\n padding-bottom: 1rem !important;\n }\n .pl-xl-3,\n .px-xl-3 {\n padding-left: 1rem !important;\n }\n .p-xl-4 {\n padding: 1.5rem !important;\n }\n .pt-xl-4,\n .py-xl-4 {\n padding-top: 1.5rem !important;\n }\n .pr-xl-4,\n .px-xl-4 {\n padding-right: 1.5rem !important;\n }\n .pb-xl-4,\n .py-xl-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-xl-4,\n .px-xl-4 {\n padding-left: 1.5rem !important;\n }\n .p-xl-5 {\n padding: 3rem !important;\n }\n .pt-xl-5,\n .py-xl-5 {\n padding-top: 3rem !important;\n }\n .pr-xl-5,\n .px-xl-5 {\n padding-right: 3rem !important;\n }\n .pb-xl-5,\n .py-xl-5 {\n padding-bottom: 3rem !important;\n }\n .pl-xl-5,\n .px-xl-5 {\n padding-left: 3rem !important;\n }\n .m-xl-n1 {\n margin: -0.25rem !important;\n }\n .mt-xl-n1,\n .my-xl-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-xl-n1,\n .mx-xl-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-xl-n1,\n .my-xl-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-xl-n1,\n .mx-xl-n1 {\n margin-left: -0.25rem !important;\n }\n .m-xl-n2 {\n margin: -0.5rem !important;\n }\n .mt-xl-n2,\n .my-xl-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-xl-n2,\n .mx-xl-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-xl-n2,\n .my-xl-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-xl-n2,\n .mx-xl-n2 {\n margin-left: -0.5rem !important;\n }\n .m-xl-n3 {\n margin: -1rem !important;\n }\n .mt-xl-n3,\n .my-xl-n3 {\n margin-top: -1rem !important;\n }\n .mr-xl-n3,\n .mx-xl-n3 {\n margin-right: -1rem !important;\n }\n .mb-xl-n3,\n .my-xl-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-xl-n3,\n .mx-xl-n3 {\n margin-left: -1rem !important;\n }\n .m-xl-n4 {\n margin: -1.5rem !important;\n }\n .mt-xl-n4,\n .my-xl-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-xl-n4,\n .mx-xl-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-xl-n4,\n .my-xl-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-xl-n4,\n .mx-xl-n4 {\n margin-left: -1.5rem !important;\n }\n .m-xl-n5 {\n margin: -3rem !important;\n }\n .mt-xl-n5,\n .my-xl-n5 {\n margin-top: -3rem !important;\n }\n .mr-xl-n5,\n .mx-xl-n5 {\n margin-right: -3rem !important;\n }\n .mb-xl-n5,\n .my-xl-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-xl-n5,\n .mx-xl-n5 {\n margin-left: -3rem !important;\n }\n .m-xl-auto {\n margin: auto !important;\n }\n .mt-xl-auto,\n .my-xl-auto {\n margin-top: auto !important;\n }\n .mr-xl-auto,\n .mx-xl-auto {\n margin-right: auto !important;\n }\n .mb-xl-auto,\n .my-xl-auto {\n margin-bottom: auto !important;\n }\n .ml-xl-auto,\n .mx-xl-auto {\n margin-left: auto !important;\n }\n}\n\n/*# sourceMappingURL=bootstrap-grid.css.map */","// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n@if $enable-grid-classes {\n // Single container class with breakpoint max-widths\n .container {\n @include make-container();\n @include make-container-max-widths();\n }\n\n // 100% wide container at all breakpoints\n .container-fluid {\n @include make-container();\n }\n\n // Responsive containers that are 100% wide until a breakpoint\n @each $breakpoint, $container-max-width in $container-max-widths {\n .container-#{$breakpoint} {\n @extend .container-fluid;\n }\n\n @include media-breakpoint-up($breakpoint, $grid-breakpoints) {\n %responsive-container-#{$breakpoint} {\n max-width: $container-max-width;\n }\n\n // Extend each breakpoint which is smaller or equal to the current breakpoint\n $extend-breakpoint: true;\n\n @each $name, $width in $grid-breakpoints {\n @if ($extend-breakpoint) {\n .container#{breakpoint-infix($name, $grid-breakpoints)} {\n @extend %responsive-container-#{$breakpoint};\n }\n\n // Once the current breakpoint is reached, stop extending\n @if ($breakpoint == $name) {\n $extend-breakpoint: false;\n }\n }\n }\n }\n }\n}\n\n\n// Row\n//\n// Rows contain your columns.\n\n@if $enable-grid-classes {\n .row {\n @include make-row();\n }\n\n // Remove the negative margin from default .row, then the horizontal padding\n // from all immediate children columns (to prevent runaway style inheritance).\n .no-gutters {\n margin-right: 0;\n margin-left: 0;\n\n > .col,\n > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n }\n }\n}\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n@if $enable-grid-classes {\n @include make-grid-columns();\n}\n","/// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n@mixin make-container($gutter: $grid-gutter-width) {\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n margin-right: auto;\n margin-left: auto;\n}\n\n\n// For each breakpoint, define the maximum width of the container in a media query\n@mixin make-container-max-widths($max-widths: $container-max-widths, $breakpoints: $grid-breakpoints) {\n @each $breakpoint, $container-max-width in $max-widths {\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n max-width: $container-max-width;\n }\n }\n}\n\n@mixin make-row($gutter: $grid-gutter-width) {\n display: flex;\n flex-wrap: wrap;\n margin-right: -$gutter / 2;\n margin-left: -$gutter / 2;\n}\n\n@mixin make-col-ready($gutter: $grid-gutter-width) {\n position: relative;\n // Prevent columns from becoming too narrow when at smaller grid tiers by\n // always setting `width: 100%;`. This works because we use `flex` values\n // later on to override this initial width.\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n}\n\n@mixin make-col($size, $columns: $grid-columns) {\n flex: 0 0 percentage($size / $columns);\n // Add a `max-width` to ensure content within each column does not blow out\n // the width of the column. Applies to IE10+ and Firefox. Chrome and Safari\n // do not appear to require this.\n max-width: percentage($size / $columns);\n}\n\n@mixin make-col-auto() {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%; // Reset earlier grid tiers\n}\n\n@mixin make-col-offset($size, $columns: $grid-columns) {\n $num: $size / $columns;\n margin-left: if($num == 0, 0, percentage($num));\n}\n\n// Row columns\n//\n// Specify on a parent element(e.g., .row) to force immediate children into NN\n// numberof columns. Supports wrapping to new lines, but does not do a Masonry\n// style grid.\n@mixin row-cols($count) {\n & > * {\n flex: 0 0 100% / $count;\n max-width: 100% / $count;\n }\n}\n","// Breakpoint viewport sizes and media queries.\n//\n// Breakpoints are defined as a map of (name: minimum width), order from small to large:\n//\n// (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)\n//\n// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.\n\n// Name of the next breakpoint, or null for the last breakpoint.\n//\n// >> breakpoint-next(sm)\n// md\n// >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// md\n// >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl))\n// md\n@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {\n $n: index($breakpoint-names, $name);\n @return if($n != null and $n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);\n}\n\n// Minimum breakpoint width. Null for the smallest (first) breakpoint.\n//\n// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 576px\n@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {\n $min: map-get($breakpoints, $name);\n @return if($min != 0, $min, null);\n}\n\n// Maximum breakpoint width. Null for the largest (last) breakpoint.\n// The maximum value is calculated as the minimum of the next one less 0.02px\n// to work around the limitations of `min-` and `max-` prefixes and viewports with fractional widths.\n// See https://www.w3.org/TR/mediaqueries-4/#mq-min-max\n// Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari.\n// See https://bugs.webkit.org/show_bug.cgi?id=178261\n//\n// >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 767.98px\n@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {\n $next: breakpoint-next($name, $breakpoints);\n @return if($next, breakpoint-min($next, $breakpoints) - .02, null);\n}\n\n// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash in front.\n// Useful for making responsive utilities.\n//\n// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"\" (Returns a blank string)\n// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"-sm\"\n@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {\n @return if(breakpoint-min($name, $breakpoints) == null, \"\", \"-#{$name}\");\n}\n\n// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.\n// Makes the @content apply to the given breakpoint and wider.\n@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n @if $min {\n @media (min-width: $min) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media of at most the maximum breakpoint width. No query for the largest breakpoint.\n// Makes the @content apply to the given breakpoint and narrower.\n@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {\n $max: breakpoint-max($name, $breakpoints);\n @if $max {\n @media (max-width: $max) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media that spans multiple breakpoint widths.\n// Makes the @content apply between the min and max breakpoints\n@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($lower, $breakpoints);\n $max: breakpoint-max($upper, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($lower, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($upper, $breakpoints) {\n @content;\n }\n }\n}\n\n// Media between the breakpoint's minimum and maximum widths.\n// No minimum for the smallest breakpoint, and no maximum for the largest one.\n// Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.\n@mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n $max: breakpoint-max($name, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($name, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($name, $breakpoints) {\n @content;\n }\n }\n}\n","// Variables\n//\n// Variables should follow the `$component-state-property-size` formula for\n// consistent naming. Ex: $nav-link-disabled-color and $modal-content-box-shadow-xs.\n\n// Color system\n\n$white: #fff !default;\n$gray-100: #f8f9fa !default;\n$gray-200: #e9ecef !default;\n$gray-300: #dee2e6 !default;\n$gray-400: #ced4da !default;\n$gray-500: #adb5bd !default;\n$gray-600: #6c757d !default;\n$gray-700: #495057 !default;\n$gray-800: #343a40 !default;\n$gray-900: #212529 !default;\n$black: #000 !default;\n\n$grays: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$grays: map-merge(\n (\n \"100\": $gray-100,\n \"200\": $gray-200,\n \"300\": $gray-300,\n \"400\": $gray-400,\n \"500\": $gray-500,\n \"600\": $gray-600,\n \"700\": $gray-700,\n \"800\": $gray-800,\n \"900\": $gray-900\n ),\n $grays\n);\n\n$blue: #007bff !default;\n$indigo: #6610f2 !default;\n$purple: #6f42c1 !default;\n$pink: #e83e8c !default;\n$red: #dc3545 !default;\n$orange: #fd7e14 !default;\n$yellow: #ffc107 !default;\n$green: #28a745 !default;\n$teal: #20c997 !default;\n$cyan: #17a2b8 !default;\n\n$colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$colors: map-merge(\n (\n \"blue\": $blue,\n \"indigo\": $indigo,\n \"purple\": $purple,\n \"pink\": $pink,\n \"red\": $red,\n \"orange\": $orange,\n \"yellow\": $yellow,\n \"green\": $green,\n \"teal\": $teal,\n \"cyan\": $cyan,\n \"white\": $white,\n \"gray\": $gray-600,\n \"gray-dark\": $gray-800\n ),\n $colors\n);\n\n$primary: $blue !default;\n$secondary: $gray-600 !default;\n$success: $green !default;\n$info: $cyan !default;\n$warning: $yellow !default;\n$danger: $red !default;\n$light: $gray-100 !default;\n$dark: $gray-800 !default;\n\n$theme-colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$theme-colors: map-merge(\n (\n \"primary\": $primary,\n \"secondary\": $secondary,\n \"success\": $success,\n \"info\": $info,\n \"warning\": $warning,\n \"danger\": $danger,\n \"light\": $light,\n \"dark\": $dark\n ),\n $theme-colors\n);\n\n// Set a specific jump point for requesting color jumps\n$theme-color-interval: 8% !default;\n\n// The yiq lightness value that determines when the lightness of color changes from \"dark\" to \"light\". Acceptable values are between 0 and 255.\n$yiq-contrasted-threshold: 150 !default;\n\n// Customize the light and dark text colors for use in our YIQ color contrast function.\n$yiq-text-dark: $gray-900 !default;\n$yiq-text-light: $white !default;\n\n// Characters which are escaped by the escape-svg function\n$escaped-characters: (\n (\"<\",\"%3c\"),\n (\">\",\"%3e\"),\n (\"#\",\"%23\"),\n (\"(\",\"%28\"),\n (\")\",\"%29\"),\n) !default;\n\n\n// Options\n//\n// Quickly modify global styling by enabling or disabling optional features.\n\n$enable-caret: true !default;\n$enable-rounded: true !default;\n$enable-shadows: false !default;\n$enable-gradients: false !default;\n$enable-transitions: true !default;\n$enable-prefers-reduced-motion-media-query: true !default;\n$enable-hover-media-query: false !default; // Deprecated, no longer affects any compiled CSS\n$enable-grid-classes: true !default;\n$enable-pointer-cursor-for-buttons: true !default;\n$enable-print-styles: true !default;\n$enable-responsive-font-sizes: false !default;\n$enable-validation-icons: true !default;\n$enable-deprecation-messages: true !default;\n\n\n// Spacing\n//\n// Control the default styling of most Bootstrap elements by modifying these\n// variables. Mostly focused on spacing.\n// You can add more entries to the $spacers map, should you need more variation.\n\n$spacer: 1rem !default;\n$spacers: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$spacers: map-merge(\n (\n 0: 0,\n 1: ($spacer * .25),\n 2: ($spacer * .5),\n 3: $spacer,\n 4: ($spacer * 1.5),\n 5: ($spacer * 3)\n ),\n $spacers\n);\n\n// This variable affects the `.h-*` and `.w-*` classes.\n$sizes: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$sizes: map-merge(\n (\n 25: 25%,\n 50: 50%,\n 75: 75%,\n 100: 100%,\n auto: auto\n ),\n $sizes\n);\n\n\n// Body\n//\n// Settings for the `` element.\n\n$body-bg: $white !default;\n$body-color: $gray-900 !default;\n\n\n// Links\n//\n// Style anchor elements.\n\n$link-color: theme-color(\"primary\") !default;\n$link-decoration: none !default;\n$link-hover-color: darken($link-color, 15%) !default;\n$link-hover-decoration: underline !default;\n// Darken percentage for links with `.text-*` class (e.g. `.text-success`)\n$emphasized-link-hover-darken-percentage: 15% !default;\n\n// Paragraphs\n//\n// Style p element.\n\n$paragraph-margin-bottom: 1rem !default;\n\n\n// Grid breakpoints\n//\n// Define the minimum dimensions at which your layout will change,\n// adapting to different screen sizes, for use in media queries.\n\n$grid-breakpoints: (\n xs: 0,\n sm: 576px,\n md: 768px,\n lg: 992px,\n xl: 1200px\n) !default;\n\n@include _assert-ascending($grid-breakpoints, \"$grid-breakpoints\");\n@include _assert-starts-at-zero($grid-breakpoints, \"$grid-breakpoints\");\n\n\n// Grid containers\n//\n// Define the maximum width of `.container` for different screen sizes.\n\n$container-max-widths: (\n sm: 540px,\n md: 720px,\n lg: 960px,\n xl: 1140px\n) !default;\n\n@include _assert-ascending($container-max-widths, \"$container-max-widths\");\n\n\n// Grid columns\n//\n// Set the number of columns and specify the width of the gutters.\n\n$grid-columns: 12 !default;\n$grid-gutter-width: 30px !default;\n$grid-row-columns: 6 !default;\n\n\n// Components\n//\n// Define common padding and border radius sizes and more.\n\n$line-height-lg: 1.5 !default;\n$line-height-sm: 1.5 !default;\n\n$border-width: 1px !default;\n$border-color: $gray-300 !default;\n\n$border-radius: .25rem !default;\n$border-radius-lg: .3rem !default;\n$border-radius-sm: .2rem !default;\n\n$rounded-pill: 50rem !default;\n\n$box-shadow-sm: 0 .125rem .25rem rgba($black, .075) !default;\n$box-shadow: 0 .5rem 1rem rgba($black, .15) !default;\n$box-shadow-lg: 0 1rem 3rem rgba($black, .175) !default;\n\n$component-active-color: $white !default;\n$component-active-bg: theme-color(\"primary\") !default;\n\n$caret-width: .3em !default;\n$caret-vertical-align: $caret-width * .85 !default;\n$caret-spacing: $caret-width * .85 !default;\n\n$transition-base: all .2s ease-in-out !default;\n$transition-fade: opacity .15s linear !default;\n$transition-collapse: height .35s ease !default;\n\n$embed-responsive-aspect-ratios: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$embed-responsive-aspect-ratios: join(\n (\n (21 9),\n (16 9),\n (4 3),\n (1 1),\n ),\n $embed-responsive-aspect-ratios\n);\n\n// Typography\n//\n// Font, line-height, and color for body text, headings, and more.\n\n// stylelint-disable value-keyword-case\n$font-family-sans-serif: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\" !default;\n$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace !default;\n$font-family-base: $font-family-sans-serif !default;\n// stylelint-enable value-keyword-case\n\n$font-size-base: 1rem !default; // Assumes the browser default, typically `16px`\n$font-size-lg: $font-size-base * 1.25 !default;\n$font-size-sm: $font-size-base * .875 !default;\n\n$font-weight-lighter: lighter !default;\n$font-weight-light: 300 !default;\n$font-weight-normal: 400 !default;\n$font-weight-bold: 700 !default;\n$font-weight-bolder: bolder !default;\n\n$font-weight-base: $font-weight-normal !default;\n$line-height-base: 1.5 !default;\n\n$h1-font-size: $font-size-base * 2.5 !default;\n$h2-font-size: $font-size-base * 2 !default;\n$h3-font-size: $font-size-base * 1.75 !default;\n$h4-font-size: $font-size-base * 1.5 !default;\n$h5-font-size: $font-size-base * 1.25 !default;\n$h6-font-size: $font-size-base !default;\n\n$headings-margin-bottom: $spacer / 2 !default;\n$headings-font-family: null !default;\n$headings-font-weight: 500 !default;\n$headings-line-height: 1.2 !default;\n$headings-color: null !default;\n\n$display1-size: 6rem !default;\n$display2-size: 5.5rem !default;\n$display3-size: 4.5rem !default;\n$display4-size: 3.5rem !default;\n\n$display1-weight: 300 !default;\n$display2-weight: 300 !default;\n$display3-weight: 300 !default;\n$display4-weight: 300 !default;\n$display-line-height: $headings-line-height !default;\n\n$lead-font-size: $font-size-base * 1.25 !default;\n$lead-font-weight: 300 !default;\n\n$small-font-size: 80% !default;\n\n$text-muted: $gray-600 !default;\n\n$blockquote-small-color: $gray-600 !default;\n$blockquote-small-font-size: $small-font-size !default;\n$blockquote-font-size: $font-size-base * 1.25 !default;\n\n$hr-border-color: rgba($black, .1) !default;\n$hr-border-width: $border-width !default;\n\n$mark-padding: .2em !default;\n\n$dt-font-weight: $font-weight-bold !default;\n\n$kbd-box-shadow: inset 0 -.1rem 0 rgba($black, .25) !default;\n$nested-kbd-font-weight: $font-weight-bold !default;\n\n$list-inline-padding: .5rem !default;\n\n$mark-bg: #fcf8e3 !default;\n\n$hr-margin-y: $spacer !default;\n\n\n// Tables\n//\n// Customizes the `.table` component with basic values, each used across all table variations.\n\n$table-cell-padding: .75rem !default;\n$table-cell-padding-sm: .3rem !default;\n\n$table-color: $body-color !default;\n$table-bg: null !default;\n$table-accent-bg: rgba($black, .05) !default;\n$table-hover-color: $table-color !default;\n$table-hover-bg: rgba($black, .075) !default;\n$table-active-bg: $table-hover-bg !default;\n\n$table-border-width: $border-width !default;\n$table-border-color: $border-color !default;\n\n$table-head-bg: $gray-200 !default;\n$table-head-color: $gray-700 !default;\n\n$table-dark-color: $white !default;\n$table-dark-bg: $gray-800 !default;\n$table-dark-accent-bg: rgba($white, .05) !default;\n$table-dark-hover-color: $table-dark-color !default;\n$table-dark-hover-bg: rgba($white, .075) !default;\n$table-dark-border-color: lighten($table-dark-bg, 7.5%) !default;\n\n$table-striped-order: odd !default;\n\n$table-caption-color: $text-muted !default;\n\n$table-bg-level: -9 !default;\n$table-border-level: -6 !default;\n\n\n// Buttons + Forms\n//\n// Shared variables that are reassigned to `$input-` and `$btn-` specific variables.\n\n$input-btn-padding-y: .375rem !default;\n$input-btn-padding-x: .75rem !default;\n$input-btn-font-family: null !default;\n$input-btn-font-size: $font-size-base !default;\n$input-btn-line-height: $line-height-base !default;\n\n$input-btn-focus-width: .2rem !default;\n$input-btn-focus-color: rgba($component-active-bg, .25) !default;\n$input-btn-focus-box-shadow: 0 0 0 $input-btn-focus-width $input-btn-focus-color !default;\n\n$input-btn-padding-y-sm: .25rem !default;\n$input-btn-padding-x-sm: .5rem !default;\n$input-btn-font-size-sm: $font-size-sm !default;\n$input-btn-line-height-sm: $line-height-sm !default;\n\n$input-btn-padding-y-lg: .5rem !default;\n$input-btn-padding-x-lg: 1rem !default;\n$input-btn-font-size-lg: $font-size-lg !default;\n$input-btn-line-height-lg: $line-height-lg !default;\n\n$input-btn-border-width: $border-width !default;\n\n\n// Buttons\n//\n// For each of Bootstrap's buttons, define text, background, and border color.\n\n$btn-padding-y: $input-btn-padding-y !default;\n$btn-padding-x: $input-btn-padding-x !default;\n$btn-font-family: $input-btn-font-family !default;\n$btn-font-size: $input-btn-font-size !default;\n$btn-line-height: $input-btn-line-height !default;\n$btn-white-space: null !default; // Set to `nowrap` to prevent text wrapping\n\n$btn-padding-y-sm: $input-btn-padding-y-sm !default;\n$btn-padding-x-sm: $input-btn-padding-x-sm !default;\n$btn-font-size-sm: $input-btn-font-size-sm !default;\n$btn-line-height-sm: $input-btn-line-height-sm !default;\n\n$btn-padding-y-lg: $input-btn-padding-y-lg !default;\n$btn-padding-x-lg: $input-btn-padding-x-lg !default;\n$btn-font-size-lg: $input-btn-font-size-lg !default;\n$btn-line-height-lg: $input-btn-line-height-lg !default;\n\n$btn-border-width: $input-btn-border-width !default;\n\n$btn-font-weight: $font-weight-normal !default;\n$btn-box-shadow: inset 0 1px 0 rgba($white, .15), 0 1px 1px rgba($black, .075) !default;\n$btn-focus-width: $input-btn-focus-width !default;\n$btn-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$btn-disabled-opacity: .65 !default;\n$btn-active-box-shadow: inset 0 3px 5px rgba($black, .125) !default;\n\n$btn-link-disabled-color: $gray-600 !default;\n\n$btn-block-spacing-y: .5rem !default;\n\n// Allows for customizing button radius independently from global border radius\n$btn-border-radius: $border-radius !default;\n$btn-border-radius-lg: $border-radius-lg !default;\n$btn-border-radius-sm: $border-radius-sm !default;\n\n$btn-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n\n// Forms\n\n$label-margin-bottom: .5rem !default;\n\n$input-padding-y: $input-btn-padding-y !default;\n$input-padding-x: $input-btn-padding-x !default;\n$input-font-family: $input-btn-font-family !default;\n$input-font-size: $input-btn-font-size !default;\n$input-font-weight: $font-weight-base !default;\n$input-line-height: $input-btn-line-height !default;\n\n$input-padding-y-sm: $input-btn-padding-y-sm !default;\n$input-padding-x-sm: $input-btn-padding-x-sm !default;\n$input-font-size-sm: $input-btn-font-size-sm !default;\n$input-line-height-sm: $input-btn-line-height-sm !default;\n\n$input-padding-y-lg: $input-btn-padding-y-lg !default;\n$input-padding-x-lg: $input-btn-padding-x-lg !default;\n$input-font-size-lg: $input-btn-font-size-lg !default;\n$input-line-height-lg: $input-btn-line-height-lg !default;\n\n$input-bg: $white !default;\n$input-disabled-bg: $gray-200 !default;\n\n$input-color: $gray-700 !default;\n$input-border-color: $gray-400 !default;\n$input-border-width: $input-btn-border-width !default;\n$input-box-shadow: inset 0 1px 1px rgba($black, .075) !default;\n\n$input-border-radius: $border-radius !default;\n$input-border-radius-lg: $border-radius-lg !default;\n$input-border-radius-sm: $border-radius-sm !default;\n\n$input-focus-bg: $input-bg !default;\n$input-focus-border-color: lighten($component-active-bg, 25%) !default;\n$input-focus-color: $input-color !default;\n$input-focus-width: $input-btn-focus-width !default;\n$input-focus-box-shadow: $input-btn-focus-box-shadow !default;\n\n$input-placeholder-color: $gray-600 !default;\n$input-plaintext-color: $body-color !default;\n\n$input-height-border: $input-border-width * 2 !default;\n\n$input-height-inner: add($input-line-height * 1em, $input-padding-y * 2) !default;\n$input-height-inner-half: add($input-line-height * .5em, $input-padding-y) !default;\n$input-height-inner-quarter: add($input-line-height * .25em, $input-padding-y / 2) !default;\n\n$input-height: add($input-line-height * 1em, add($input-padding-y * 2, $input-height-border, false)) !default;\n$input-height-sm: add($input-line-height-sm * 1em, add($input-padding-y-sm * 2, $input-height-border, false)) !default;\n$input-height-lg: add($input-line-height-lg * 1em, add($input-padding-y-lg * 2, $input-height-border, false)) !default;\n\n$input-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$form-text-margin-top: .25rem !default;\n\n$form-check-input-gutter: 1.25rem !default;\n$form-check-input-margin-y: .3rem !default;\n$form-check-input-margin-x: .25rem !default;\n\n$form-check-inline-margin-x: .75rem !default;\n$form-check-inline-input-margin-x: .3125rem !default;\n\n$form-grid-gutter-width: 10px !default;\n$form-group-margin-bottom: 1rem !default;\n\n$input-group-addon-color: $input-color !default;\n$input-group-addon-bg: $gray-200 !default;\n$input-group-addon-border-color: $input-border-color !default;\n\n$custom-forms-transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$custom-control-gutter: .5rem !default;\n$custom-control-spacer-x: 1rem !default;\n$custom-control-cursor: null !default;\n\n$custom-control-indicator-size: 1rem !default;\n$custom-control-indicator-bg: $input-bg !default;\n\n$custom-control-indicator-bg-size: 50% 50% !default;\n$custom-control-indicator-box-shadow: $input-box-shadow !default;\n$custom-control-indicator-border-color: $gray-500 !default;\n$custom-control-indicator-border-width: $input-border-width !default;\n\n$custom-control-label-color: null !default;\n\n$custom-control-indicator-disabled-bg: $input-disabled-bg !default;\n$custom-control-label-disabled-color: $gray-600 !default;\n\n$custom-control-indicator-checked-color: $component-active-color !default;\n$custom-control-indicator-checked-bg: $component-active-bg !default;\n$custom-control-indicator-checked-disabled-bg: rgba(theme-color(\"primary\"), .5) !default;\n$custom-control-indicator-checked-box-shadow: none !default;\n$custom-control-indicator-checked-border-color: $custom-control-indicator-checked-bg !default;\n\n$custom-control-indicator-focus-box-shadow: $input-focus-box-shadow !default;\n$custom-control-indicator-focus-border-color: $input-focus-border-color !default;\n\n$custom-control-indicator-active-color: $component-active-color !default;\n$custom-control-indicator-active-bg: lighten($component-active-bg, 35%) !default;\n$custom-control-indicator-active-box-shadow: none !default;\n$custom-control-indicator-active-border-color: $custom-control-indicator-active-bg !default;\n\n$custom-checkbox-indicator-border-radius: $border-radius !default;\n$custom-checkbox-indicator-icon-checked: url(\"data:image/svg+xml,\") !default;\n\n$custom-checkbox-indicator-indeterminate-bg: $component-active-bg !default;\n$custom-checkbox-indicator-indeterminate-color: $custom-control-indicator-checked-color !default;\n$custom-checkbox-indicator-icon-indeterminate: url(\"data:image/svg+xml,\") !default;\n$custom-checkbox-indicator-indeterminate-box-shadow: none !default;\n$custom-checkbox-indicator-indeterminate-border-color: $custom-checkbox-indicator-indeterminate-bg !default;\n\n$custom-radio-indicator-border-radius: 50% !default;\n$custom-radio-indicator-icon-checked: url(\"data:image/svg+xml,\") !default;\n\n$custom-switch-width: $custom-control-indicator-size * 1.75 !default;\n$custom-switch-indicator-border-radius: $custom-control-indicator-size / 2 !default;\n$custom-switch-indicator-size: subtract($custom-control-indicator-size, $custom-control-indicator-border-width * 4) !default;\n\n$custom-select-padding-y: $input-padding-y !default;\n$custom-select-padding-x: $input-padding-x !default;\n$custom-select-font-family: $input-font-family !default;\n$custom-select-font-size: $input-font-size !default;\n$custom-select-height: $input-height !default;\n$custom-select-indicator-padding: 1rem !default; // Extra padding to account for the presence of the background-image based indicator\n$custom-select-font-weight: $input-font-weight !default;\n$custom-select-line-height: $input-line-height !default;\n$custom-select-color: $input-color !default;\n$custom-select-disabled-color: $gray-600 !default;\n$custom-select-bg: $input-bg !default;\n$custom-select-disabled-bg: $gray-200 !default;\n$custom-select-bg-size: 8px 10px !default; // In pixels because image dimensions\n$custom-select-indicator-color: $gray-800 !default;\n$custom-select-indicator: url(\"data:image/svg+xml,\") !default;\n$custom-select-background: escape-svg($custom-select-indicator) no-repeat right $custom-select-padding-x center / $custom-select-bg-size !default; // Used so we can have multiple background elements (e.g., arrow and feedback icon)\n\n$custom-select-feedback-icon-padding-right: add(1em * .75, (2 * $custom-select-padding-y * .75) + $custom-select-padding-x + $custom-select-indicator-padding) !default;\n$custom-select-feedback-icon-position: center right ($custom-select-padding-x + $custom-select-indicator-padding) !default;\n$custom-select-feedback-icon-size: $input-height-inner-half $input-height-inner-half !default;\n\n$custom-select-border-width: $input-border-width !default;\n$custom-select-border-color: $input-border-color !default;\n$custom-select-border-radius: $border-radius !default;\n$custom-select-box-shadow: inset 0 1px 2px rgba($black, .075) !default;\n\n$custom-select-focus-border-color: $input-focus-border-color !default;\n$custom-select-focus-width: $input-focus-width !default;\n$custom-select-focus-box-shadow: 0 0 0 $custom-select-focus-width $input-btn-focus-color !default;\n\n$custom-select-padding-y-sm: $input-padding-y-sm !default;\n$custom-select-padding-x-sm: $input-padding-x-sm !default;\n$custom-select-font-size-sm: $input-font-size-sm !default;\n$custom-select-height-sm: $input-height-sm !default;\n\n$custom-select-padding-y-lg: $input-padding-y-lg !default;\n$custom-select-padding-x-lg: $input-padding-x-lg !default;\n$custom-select-font-size-lg: $input-font-size-lg !default;\n$custom-select-height-lg: $input-height-lg !default;\n\n$custom-range-track-width: 100% !default;\n$custom-range-track-height: .5rem !default;\n$custom-range-track-cursor: pointer !default;\n$custom-range-track-bg: $gray-300 !default;\n$custom-range-track-border-radius: 1rem !default;\n$custom-range-track-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default;\n\n$custom-range-thumb-width: 1rem !default;\n$custom-range-thumb-height: $custom-range-thumb-width !default;\n$custom-range-thumb-bg: $component-active-bg !default;\n$custom-range-thumb-border: 0 !default;\n$custom-range-thumb-border-radius: 1rem !default;\n$custom-range-thumb-box-shadow: 0 .1rem .25rem rgba($black, .1) !default;\n$custom-range-thumb-focus-box-shadow: 0 0 0 1px $body-bg, $input-focus-box-shadow !default;\n$custom-range-thumb-focus-box-shadow-width: $input-focus-width !default; // For focus box shadow issue in IE/Edge\n$custom-range-thumb-active-bg: lighten($component-active-bg, 35%) !default;\n$custom-range-thumb-disabled-bg: $gray-500 !default;\n\n$custom-file-height: $input-height !default;\n$custom-file-height-inner: $input-height-inner !default;\n$custom-file-focus-border-color: $input-focus-border-color !default;\n$custom-file-focus-box-shadow: $input-focus-box-shadow !default;\n$custom-file-disabled-bg: $input-disabled-bg !default;\n\n$custom-file-padding-y: $input-padding-y !default;\n$custom-file-padding-x: $input-padding-x !default;\n$custom-file-line-height: $input-line-height !default;\n$custom-file-font-family: $input-font-family !default;\n$custom-file-font-weight: $input-font-weight !default;\n$custom-file-color: $input-color !default;\n$custom-file-bg: $input-bg !default;\n$custom-file-border-width: $input-border-width !default;\n$custom-file-border-color: $input-border-color !default;\n$custom-file-border-radius: $input-border-radius !default;\n$custom-file-box-shadow: $input-box-shadow !default;\n$custom-file-button-color: $custom-file-color !default;\n$custom-file-button-bg: $input-group-addon-bg !default;\n$custom-file-text: (\n en: \"Browse\"\n) !default;\n\n\n// Form validation\n\n$form-feedback-margin-top: $form-text-margin-top !default;\n$form-feedback-font-size: $small-font-size !default;\n$form-feedback-valid-color: theme-color(\"success\") !default;\n$form-feedback-invalid-color: theme-color(\"danger\") !default;\n\n$form-feedback-icon-valid-color: $form-feedback-valid-color !default;\n$form-feedback-icon-valid: url(\"data:image/svg+xml,\") !default;\n$form-feedback-icon-invalid-color: $form-feedback-invalid-color !default;\n$form-feedback-icon-invalid: url(\"data:image/svg+xml,\") !default;\n\n$form-validation-states: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$form-validation-states: map-merge(\n (\n \"valid\": (\n \"color\": $form-feedback-valid-color,\n \"icon\": $form-feedback-icon-valid\n ),\n \"invalid\": (\n \"color\": $form-feedback-invalid-color,\n \"icon\": $form-feedback-icon-invalid\n ),\n ),\n $form-validation-states\n);\n\n// Z-index master list\n//\n// Warning: Avoid customizing these values. They're used for a bird's eye view\n// of components dependent on the z-axis and are designed to all work together.\n\n$zindex-dropdown: 1000 !default;\n$zindex-sticky: 1020 !default;\n$zindex-fixed: 1030 !default;\n$zindex-modal-backdrop: 1040 !default;\n$zindex-modal: 1050 !default;\n$zindex-popover: 1060 !default;\n$zindex-tooltip: 1070 !default;\n\n\n// Navs\n\n$nav-link-padding-y: .5rem !default;\n$nav-link-padding-x: 1rem !default;\n$nav-link-disabled-color: $gray-600 !default;\n\n$nav-tabs-border-color: $gray-300 !default;\n$nav-tabs-border-width: $border-width !default;\n$nav-tabs-border-radius: $border-radius !default;\n$nav-tabs-link-hover-border-color: $gray-200 $gray-200 $nav-tabs-border-color !default;\n$nav-tabs-link-active-color: $gray-700 !default;\n$nav-tabs-link-active-bg: $body-bg !default;\n$nav-tabs-link-active-border-color: $gray-300 $gray-300 $nav-tabs-link-active-bg !default;\n\n$nav-pills-border-radius: $border-radius !default;\n$nav-pills-link-active-color: $component-active-color !default;\n$nav-pills-link-active-bg: $component-active-bg !default;\n\n$nav-divider-color: $gray-200 !default;\n$nav-divider-margin-y: $spacer / 2 !default;\n\n\n// Navbar\n\n$navbar-padding-y: $spacer / 2 !default;\n$navbar-padding-x: $spacer !default;\n\n$navbar-nav-link-padding-x: .5rem !default;\n\n$navbar-brand-font-size: $font-size-lg !default;\n// Compute the navbar-brand padding-y so the navbar-brand will have the same height as navbar-text and nav-link\n$nav-link-height: $font-size-base * $line-height-base + $nav-link-padding-y * 2 !default;\n$navbar-brand-height: $navbar-brand-font-size * $line-height-base !default;\n$navbar-brand-padding-y: ($nav-link-height - $navbar-brand-height) / 2 !default;\n\n$navbar-toggler-padding-y: .25rem !default;\n$navbar-toggler-padding-x: .75rem !default;\n$navbar-toggler-font-size: $font-size-lg !default;\n$navbar-toggler-border-radius: $btn-border-radius !default;\n\n$navbar-dark-color: rgba($white, .5) !default;\n$navbar-dark-hover-color: rgba($white, .75) !default;\n$navbar-dark-active-color: $white !default;\n$navbar-dark-disabled-color: rgba($white, .25) !default;\n$navbar-dark-toggler-icon-bg: url(\"data:image/svg+xml,\") !default;\n$navbar-dark-toggler-border-color: rgba($white, .1) !default;\n\n$navbar-light-color: rgba($black, .5) !default;\n$navbar-light-hover-color: rgba($black, .7) !default;\n$navbar-light-active-color: rgba($black, .9) !default;\n$navbar-light-disabled-color: rgba($black, .3) !default;\n$navbar-light-toggler-icon-bg: url(\"data:image/svg+xml,\") !default;\n$navbar-light-toggler-border-color: rgba($black, .1) !default;\n\n$navbar-light-brand-color: $navbar-light-active-color !default;\n$navbar-light-brand-hover-color: $navbar-light-active-color !default;\n$navbar-dark-brand-color: $navbar-dark-active-color !default;\n$navbar-dark-brand-hover-color: $navbar-dark-active-color !default;\n\n\n// Dropdowns\n//\n// Dropdown menu container and contents.\n\n$dropdown-min-width: 10rem !default;\n$dropdown-padding-y: .5rem !default;\n$dropdown-spacer: .125rem !default;\n$dropdown-font-size: $font-size-base !default;\n$dropdown-color: $body-color !default;\n$dropdown-bg: $white !default;\n$dropdown-border-color: rgba($black, .15) !default;\n$dropdown-border-radius: $border-radius !default;\n$dropdown-border-width: $border-width !default;\n$dropdown-inner-border-radius: subtract($dropdown-border-radius, $dropdown-border-width) !default;\n$dropdown-divider-bg: $gray-200 !default;\n$dropdown-divider-margin-y: $nav-divider-margin-y !default;\n$dropdown-box-shadow: 0 .5rem 1rem rgba($black, .175) !default;\n\n$dropdown-link-color: $gray-900 !default;\n$dropdown-link-hover-color: darken($gray-900, 5%) !default;\n$dropdown-link-hover-bg: $gray-100 !default;\n\n$dropdown-link-active-color: $component-active-color !default;\n$dropdown-link-active-bg: $component-active-bg !default;\n\n$dropdown-link-disabled-color: $gray-600 !default;\n\n$dropdown-item-padding-y: .25rem !default;\n$dropdown-item-padding-x: 1.5rem !default;\n\n$dropdown-header-color: $gray-600 !default;\n$dropdown-header-padding: $dropdown-padding-y $dropdown-item-padding-x !default;\n\n\n// Pagination\n\n$pagination-padding-y: .5rem !default;\n$pagination-padding-x: .75rem !default;\n$pagination-padding-y-sm: .25rem !default;\n$pagination-padding-x-sm: .5rem !default;\n$pagination-padding-y-lg: .75rem !default;\n$pagination-padding-x-lg: 1.5rem !default;\n$pagination-line-height: 1.25 !default;\n\n$pagination-color: $link-color !default;\n$pagination-bg: $white !default;\n$pagination-border-width: $border-width !default;\n$pagination-border-color: $gray-300 !default;\n\n$pagination-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$pagination-focus-outline: 0 !default;\n\n$pagination-hover-color: $link-hover-color !default;\n$pagination-hover-bg: $gray-200 !default;\n$pagination-hover-border-color: $gray-300 !default;\n\n$pagination-active-color: $component-active-color !default;\n$pagination-active-bg: $component-active-bg !default;\n$pagination-active-border-color: $pagination-active-bg !default;\n\n$pagination-disabled-color: $gray-600 !default;\n$pagination-disabled-bg: $white !default;\n$pagination-disabled-border-color: $gray-300 !default;\n\n\n// Jumbotron\n\n$jumbotron-padding: 2rem !default;\n$jumbotron-color: null !default;\n$jumbotron-bg: $gray-200 !default;\n\n\n// Cards\n\n$card-spacer-y: .75rem !default;\n$card-spacer-x: 1.25rem !default;\n$card-border-width: $border-width !default;\n$card-border-radius: $border-radius !default;\n$card-border-color: rgba($black, .125) !default;\n$card-inner-border-radius: subtract($card-border-radius, $card-border-width) !default;\n$card-cap-bg: rgba($black, .03) !default;\n$card-cap-color: null !default;\n$card-height: null !default;\n$card-color: null !default;\n$card-bg: $white !default;\n\n$card-img-overlay-padding: 1.25rem !default;\n\n$card-group-margin: $grid-gutter-width / 2 !default;\n$card-deck-margin: $card-group-margin !default;\n\n$card-columns-count: 3 !default;\n$card-columns-gap: 1.25rem !default;\n$card-columns-margin: $card-spacer-y !default;\n\n\n// Tooltips\n\n$tooltip-font-size: $font-size-sm !default;\n$tooltip-max-width: 200px !default;\n$tooltip-color: $white !default;\n$tooltip-bg: $black !default;\n$tooltip-border-radius: $border-radius !default;\n$tooltip-opacity: .9 !default;\n$tooltip-padding-y: .25rem !default;\n$tooltip-padding-x: .5rem !default;\n$tooltip-margin: 0 !default;\n\n$tooltip-arrow-width: .8rem !default;\n$tooltip-arrow-height: .4rem !default;\n$tooltip-arrow-color: $tooltip-bg !default;\n\n// Form tooltips must come after regular tooltips\n$form-feedback-tooltip-padding-y: $tooltip-padding-y !default;\n$form-feedback-tooltip-padding-x: $tooltip-padding-x !default;\n$form-feedback-tooltip-font-size: $tooltip-font-size !default;\n$form-feedback-tooltip-line-height: $line-height-base !default;\n$form-feedback-tooltip-opacity: $tooltip-opacity !default;\n$form-feedback-tooltip-border-radius: $tooltip-border-radius !default;\n\n\n// Popovers\n\n$popover-font-size: $font-size-sm !default;\n$popover-bg: $white !default;\n$popover-max-width: 276px !default;\n$popover-border-width: $border-width !default;\n$popover-border-color: rgba($black, .2) !default;\n$popover-border-radius: $border-radius-lg !default;\n$popover-inner-border-radius: subtract($popover-border-radius, $popover-border-width) !default;\n$popover-box-shadow: 0 .25rem .5rem rgba($black, .2) !default;\n\n$popover-header-bg: darken($popover-bg, 3%) !default;\n$popover-header-color: $headings-color !default;\n$popover-header-padding-y: .5rem !default;\n$popover-header-padding-x: .75rem !default;\n\n$popover-body-color: $body-color !default;\n$popover-body-padding-y: $popover-header-padding-y !default;\n$popover-body-padding-x: $popover-header-padding-x !default;\n\n$popover-arrow-width: 1rem !default;\n$popover-arrow-height: .5rem !default;\n$popover-arrow-color: $popover-bg !default;\n\n$popover-arrow-outer-color: fade-in($popover-border-color, .05) !default;\n\n\n// Toasts\n\n$toast-max-width: 350px !default;\n$toast-padding-x: .75rem !default;\n$toast-padding-y: .25rem !default;\n$toast-font-size: .875rem !default;\n$toast-color: null !default;\n$toast-background-color: rgba($white, .85) !default;\n$toast-border-width: 1px !default;\n$toast-border-color: rgba(0, 0, 0, .1) !default;\n$toast-border-radius: .25rem !default;\n$toast-box-shadow: 0 .25rem .75rem rgba($black, .1) !default;\n\n$toast-header-color: $gray-600 !default;\n$toast-header-background-color: rgba($white, .85) !default;\n$toast-header-border-color: rgba(0, 0, 0, .05) !default;\n\n\n// Badges\n\n$badge-font-size: 75% !default;\n$badge-font-weight: $font-weight-bold !default;\n$badge-padding-y: .25em !default;\n$badge-padding-x: .4em !default;\n$badge-border-radius: $border-radius !default;\n\n$badge-transition: $btn-transition !default;\n$badge-focus-width: $input-btn-focus-width !default;\n\n$badge-pill-padding-x: .6em !default;\n// Use a higher than normal value to ensure completely rounded edges when\n// customizing padding or font-size on labels.\n$badge-pill-border-radius: 10rem !default;\n\n\n// Modals\n\n// Padding applied to the modal body\n$modal-inner-padding: 1rem !default;\n\n// Margin between elements in footer, must be lower than or equal to 2 * $modal-inner-padding\n$modal-footer-margin-between: .5rem !default;\n\n$modal-dialog-margin: .5rem !default;\n$modal-dialog-margin-y-sm-up: 1.75rem !default;\n\n$modal-title-line-height: $line-height-base !default;\n\n$modal-content-color: null !default;\n$modal-content-bg: $white !default;\n$modal-content-border-color: rgba($black, .2) !default;\n$modal-content-border-width: $border-width !default;\n$modal-content-border-radius: $border-radius-lg !default;\n$modal-content-inner-border-radius: subtract($modal-content-border-radius, $modal-content-border-width) !default;\n$modal-content-box-shadow-xs: 0 .25rem .5rem rgba($black, .5) !default;\n$modal-content-box-shadow-sm-up: 0 .5rem 1rem rgba($black, .5) !default;\n\n$modal-backdrop-bg: $black !default;\n$modal-backdrop-opacity: .5 !default;\n$modal-header-border-color: $border-color !default;\n$modal-footer-border-color: $modal-header-border-color !default;\n$modal-header-border-width: $modal-content-border-width !default;\n$modal-footer-border-width: $modal-header-border-width !default;\n$modal-header-padding-y: 1rem !default;\n$modal-header-padding-x: 1rem !default;\n$modal-header-padding: $modal-header-padding-y $modal-header-padding-x !default; // Keep this for backwards compatibility\n\n$modal-xl: 1140px !default;\n$modal-lg: 800px !default;\n$modal-md: 500px !default;\n$modal-sm: 300px !default;\n\n$modal-fade-transform: translate(0, -50px) !default;\n$modal-show-transform: none !default;\n$modal-transition: transform .3s ease-out !default;\n$modal-scale-transform: scale(1.02) !default;\n\n\n// Alerts\n//\n// Define alert colors, border radius, and padding.\n\n$alert-padding-y: .75rem !default;\n$alert-padding-x: 1.25rem !default;\n$alert-margin-bottom: 1rem !default;\n$alert-border-radius: $border-radius !default;\n$alert-link-font-weight: $font-weight-bold !default;\n$alert-border-width: $border-width !default;\n\n$alert-bg-level: -10 !default;\n$alert-border-level: -9 !default;\n$alert-color-level: 6 !default;\n\n\n// Progress bars\n\n$progress-height: 1rem !default;\n$progress-font-size: $font-size-base * .75 !default;\n$progress-bg: $gray-200 !default;\n$progress-border-radius: $border-radius !default;\n$progress-box-shadow: inset 0 .1rem .1rem rgba($black, .1) !default;\n$progress-bar-color: $white !default;\n$progress-bar-bg: theme-color(\"primary\") !default;\n$progress-bar-animation-timing: 1s linear infinite !default;\n$progress-bar-transition: width .6s ease !default;\n\n\n// List group\n\n$list-group-color: null !default;\n$list-group-bg: $white !default;\n$list-group-border-color: rgba($black, .125) !default;\n$list-group-border-width: $border-width !default;\n$list-group-border-radius: $border-radius !default;\n\n$list-group-item-padding-y: .75rem !default;\n$list-group-item-padding-x: 1.25rem !default;\n\n$list-group-hover-bg: $gray-100 !default;\n$list-group-active-color: $component-active-color !default;\n$list-group-active-bg: $component-active-bg !default;\n$list-group-active-border-color: $list-group-active-bg !default;\n\n$list-group-disabled-color: $gray-600 !default;\n$list-group-disabled-bg: $list-group-bg !default;\n\n$list-group-action-color: $gray-700 !default;\n$list-group-action-hover-color: $list-group-action-color !default;\n\n$list-group-action-active-color: $body-color !default;\n$list-group-action-active-bg: $gray-200 !default;\n\n\n// Image thumbnails\n\n$thumbnail-padding: .25rem !default;\n$thumbnail-bg: $body-bg !default;\n$thumbnail-border-width: $border-width !default;\n$thumbnail-border-color: $gray-300 !default;\n$thumbnail-border-radius: $border-radius !default;\n$thumbnail-box-shadow: 0 1px 2px rgba($black, .075) !default;\n\n\n// Figures\n\n$figure-caption-font-size: 90% !default;\n$figure-caption-color: $gray-600 !default;\n\n\n// Breadcrumbs\n\n$breadcrumb-font-size: null !default;\n\n$breadcrumb-padding-y: .75rem !default;\n$breadcrumb-padding-x: 1rem !default;\n$breadcrumb-item-padding: .5rem !default;\n\n$breadcrumb-margin-bottom: 1rem !default;\n\n$breadcrumb-bg: $gray-200 !default;\n$breadcrumb-divider-color: $gray-600 !default;\n$breadcrumb-active-color: $gray-600 !default;\n$breadcrumb-divider: quote(\"/\") !default;\n\n$breadcrumb-border-radius: $border-radius !default;\n\n\n// Carousel\n\n$carousel-control-color: $white !default;\n$carousel-control-width: 15% !default;\n$carousel-control-opacity: .5 !default;\n$carousel-control-hover-opacity: .9 !default;\n$carousel-control-transition: opacity .15s ease !default;\n\n$carousel-indicator-width: 30px !default;\n$carousel-indicator-height: 3px !default;\n$carousel-indicator-hit-area-height: 10px !default;\n$carousel-indicator-spacer: 3px !default;\n$carousel-indicator-active-bg: $white !default;\n$carousel-indicator-transition: opacity .6s ease !default;\n\n$carousel-caption-width: 70% !default;\n$carousel-caption-color: $white !default;\n\n$carousel-control-icon-width: 20px !default;\n\n$carousel-control-prev-icon-bg: url(\"data:image/svg+xml,\") !default;\n$carousel-control-next-icon-bg: url(\"data:image/svg+xml,\") !default;\n\n$carousel-transition-duration: .6s !default;\n$carousel-transition: transform $carousel-transition-duration ease-in-out !default; // Define transform transition first if using multiple transitions (e.g., `transform 2s ease, opacity .5s ease-out`)\n\n\n// Spinners\n\n$spinner-width: 2rem !default;\n$spinner-height: $spinner-width !default;\n$spinner-border-width: .25em !default;\n\n$spinner-width-sm: 1rem !default;\n$spinner-height-sm: $spinner-width-sm !default;\n$spinner-border-width-sm: .2em !default;\n\n\n// Close\n\n$close-font-size: $font-size-base * 1.5 !default;\n$close-font-weight: $font-weight-bold !default;\n$close-color: $black !default;\n$close-text-shadow: 0 1px 0 $white !default;\n\n\n// Code\n\n$code-font-size: 87.5% !default;\n$code-color: $pink !default;\n\n$kbd-padding-y: .2rem !default;\n$kbd-padding-x: .4rem !default;\n$kbd-font-size: $code-font-size !default;\n$kbd-color: $white !default;\n$kbd-bg: $gray-900 !default;\n\n$pre-color: $gray-900 !default;\n$pre-scrollable-max-height: 340px !default;\n\n\n// Utilities\n\n$displays: none, inline, inline-block, block, table, table-row, table-cell, flex, inline-flex !default;\n$overflows: auto, hidden !default;\n$positions: static, relative, absolute, fixed, sticky !default;\n$user-selects: all, auto, none !default;\n\n\n// Printing\n\n$print-page-size: a3 !default;\n$print-body-min-width: map-get($grid-breakpoints, \"lg\") !default;\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `$grid-columns`.\n\n@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) {\n // Common properties for all breakpoints\n %grid-column {\n position: relative;\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n }\n\n @each $breakpoint in map-keys($breakpoints) {\n $infix: breakpoint-infix($breakpoint, $breakpoints);\n\n @if $columns > 0 {\n // Allow columns to stretch full width below their breakpoints\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @extend %grid-column;\n }\n }\n }\n\n .col#{$infix},\n .col#{$infix}-auto {\n @extend %grid-column;\n }\n\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n // Provide basic `.col-{bp}` classes for equal-width flexbox columns\n .col#{$infix} {\n flex-basis: 0;\n flex-grow: 1;\n min-width: 0; // See https://github.com/twbs/bootstrap/issues/25410\n max-width: 100%;\n }\n\n @if $grid-row-columns > 0 {\n @for $i from 1 through $grid-row-columns {\n .row-cols#{$infix}-#{$i} {\n @include row-cols($i);\n }\n }\n }\n\n .col#{$infix}-auto {\n @include make-col-auto();\n }\n\n @if $columns > 0 {\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @include make-col($i, $columns);\n }\n }\n }\n\n .order#{$infix}-first { order: -1; }\n\n .order#{$infix}-last { order: $columns + 1; }\n\n @for $i from 0 through $columns {\n .order#{$infix}-#{$i} { order: $i; }\n }\n\n @if $columns > 0 {\n // `$columns - 1` because offsetting by the width of an entire row isn't possible\n @for $i from 0 through ($columns - 1) {\n @if not ($infix == \"\" and $i == 0) { // Avoid emitting useless .offset-0\n .offset#{$infix}-#{$i} {\n @include make-col-offset($i, $columns);\n }\n }\n }\n }\n }\n }\n}\n","// stylelint-disable declaration-no-important\n\n//\n// Utilities for common `display` values\n//\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n @each $value in $displays {\n .d#{$infix}-#{$value} { display: $value !important; }\n }\n }\n}\n\n\n//\n// Utilities for toggling `display` in print\n//\n\n@media print {\n @each $value in $displays {\n .d-print-#{$value} { display: $value !important; }\n }\n}\n","// stylelint-disable declaration-no-important\n\n// Flex variation\n//\n// Custom styles for additional flex alignment options.\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n .flex#{$infix}-row { flex-direction: row !important; }\n .flex#{$infix}-column { flex-direction: column !important; }\n .flex#{$infix}-row-reverse { flex-direction: row-reverse !important; }\n .flex#{$infix}-column-reverse { flex-direction: column-reverse !important; }\n\n .flex#{$infix}-wrap { flex-wrap: wrap !important; }\n .flex#{$infix}-nowrap { flex-wrap: nowrap !important; }\n .flex#{$infix}-wrap-reverse { flex-wrap: wrap-reverse !important; }\n .flex#{$infix}-fill { flex: 1 1 auto !important; }\n .flex#{$infix}-grow-0 { flex-grow: 0 !important; }\n .flex#{$infix}-grow-1 { flex-grow: 1 !important; }\n .flex#{$infix}-shrink-0 { flex-shrink: 0 !important; }\n .flex#{$infix}-shrink-1 { flex-shrink: 1 !important; }\n\n .justify-content#{$infix}-start { justify-content: flex-start !important; }\n .justify-content#{$infix}-end { justify-content: flex-end !important; }\n .justify-content#{$infix}-center { justify-content: center !important; }\n .justify-content#{$infix}-between { justify-content: space-between !important; }\n .justify-content#{$infix}-around { justify-content: space-around !important; }\n\n .align-items#{$infix}-start { align-items: flex-start !important; }\n .align-items#{$infix}-end { align-items: flex-end !important; }\n .align-items#{$infix}-center { align-items: center !important; }\n .align-items#{$infix}-baseline { align-items: baseline !important; }\n .align-items#{$infix}-stretch { align-items: stretch !important; }\n\n .align-content#{$infix}-start { align-content: flex-start !important; }\n .align-content#{$infix}-end { align-content: flex-end !important; }\n .align-content#{$infix}-center { align-content: center !important; }\n .align-content#{$infix}-between { align-content: space-between !important; }\n .align-content#{$infix}-around { align-content: space-around !important; }\n .align-content#{$infix}-stretch { align-content: stretch !important; }\n\n .align-self#{$infix}-auto { align-self: auto !important; }\n .align-self#{$infix}-start { align-self: flex-start !important; }\n .align-self#{$infix}-end { align-self: flex-end !important; }\n .align-self#{$infix}-center { align-self: center !important; }\n .align-self#{$infix}-baseline { align-self: baseline !important; }\n .align-self#{$infix}-stretch { align-self: stretch !important; }\n }\n}\n","// stylelint-disable declaration-no-important\n\n// Margin and Padding\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n @each $prop, $abbrev in (margin: m, padding: p) {\n @each $size, $length in $spacers {\n .#{$abbrev}#{$infix}-#{$size} { #{$prop}: $length !important; }\n .#{$abbrev}t#{$infix}-#{$size},\n .#{$abbrev}y#{$infix}-#{$size} {\n #{$prop}-top: $length !important;\n }\n .#{$abbrev}r#{$infix}-#{$size},\n .#{$abbrev}x#{$infix}-#{$size} {\n #{$prop}-right: $length !important;\n }\n .#{$abbrev}b#{$infix}-#{$size},\n .#{$abbrev}y#{$infix}-#{$size} {\n #{$prop}-bottom: $length !important;\n }\n .#{$abbrev}l#{$infix}-#{$size},\n .#{$abbrev}x#{$infix}-#{$size} {\n #{$prop}-left: $length !important;\n }\n }\n }\n\n // Negative margins (e.g., where `.mb-n1` is negative version of `.mb-1`)\n @each $size, $length in $spacers {\n @if $size != 0 {\n .m#{$infix}-n#{$size} { margin: -$length !important; }\n .mt#{$infix}-n#{$size},\n .my#{$infix}-n#{$size} {\n margin-top: -$length !important;\n }\n .mr#{$infix}-n#{$size},\n .mx#{$infix}-n#{$size} {\n margin-right: -$length !important;\n }\n .mb#{$infix}-n#{$size},\n .my#{$infix}-n#{$size} {\n margin-bottom: -$length !important;\n }\n .ml#{$infix}-n#{$size},\n .mx#{$infix}-n#{$size} {\n margin-left: -$length !important;\n }\n }\n }\n\n // Some special margin utils\n .m#{$infix}-auto { margin: auto !important; }\n .mt#{$infix}-auto,\n .my#{$infix}-auto {\n margin-top: auto !important;\n }\n .mr#{$infix}-auto,\n .mx#{$infix}-auto {\n margin-right: auto !important;\n }\n .mb#{$infix}-auto,\n .my#{$infix}-auto {\n margin-bottom: auto !important;\n }\n .ml#{$infix}-auto,\n .mx#{$infix}-auto {\n margin-left: auto !important;\n }\n }\n}\n"]} \ No newline at end of file diff --git a/assets/ext/bootstrap/css/bootstrap-grid.min.css b/assets/ext/bootstrap/css/bootstrap-grid.min.css new file mode 100644 index 00000000..b40eb5f7 --- /dev/null +++ b/assets/ext/bootstrap/css/bootstrap-grid.min.css @@ -0,0 +1,7 @@ +/*! + * Bootstrap Grid v4.5.0 (https://getbootstrap.com/) + * Copyright 2011-2020 The Bootstrap Authors + * Copyright 2011-2020 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */html{box-sizing:border-box;-ms-overflow-style:scrollbar}*,::after,::before{box-sizing:inherit}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container{max-width:540px}}@media (min-width:768px){.container{max-width:720px}}@media (min-width:992px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1140px}}.container-fluid,.container-lg,.container-md,.container-sm,.container-xl{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container,.container-sm{max-width:540px}}@media (min-width:768px){.container,.container-md,.container-sm{max-width:720px}}@media (min-width:992px){.container,.container-lg,.container-md,.container-sm{max-width:960px}}@media (min-width:1200px){.container,.container-lg,.container-md,.container-sm,.container-xl{max-width:1140px}}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;min-width:0;max-width:100%}.row-cols-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-ms-flex-order:-1;order:-1}.order-last{-ms-flex-order:13;order:13}.order-0{-ms-flex-order:0;order:0}.order-1{-ms-flex-order:1;order:1}.order-2{-ms-flex-order:2;order:2}.order-3{-ms-flex-order:3;order:3}.order-4{-ms-flex-order:4;order:4}.order-5{-ms-flex-order:5;order:5}.order-6{-ms-flex-order:6;order:6}.order-7{-ms-flex-order:7;order:7}.order-8{-ms-flex-order:8;order:8}.order-9{-ms-flex-order:9;order:9}.order-10{-ms-flex-order:10;order:10}.order-11{-ms-flex-order:11;order:11}.order-12{-ms-flex-order:12;order:12}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;min-width:0;max-width:100%}.row-cols-sm-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-sm-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-sm-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-sm-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-sm-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-sm-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-sm-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-ms-flex-order:-1;order:-1}.order-sm-last{-ms-flex-order:13;order:13}.order-sm-0{-ms-flex-order:0;order:0}.order-sm-1{-ms-flex-order:1;order:1}.order-sm-2{-ms-flex-order:2;order:2}.order-sm-3{-ms-flex-order:3;order:3}.order-sm-4{-ms-flex-order:4;order:4}.order-sm-5{-ms-flex-order:5;order:5}.order-sm-6{-ms-flex-order:6;order:6}.order-sm-7{-ms-flex-order:7;order:7}.order-sm-8{-ms-flex-order:8;order:8}.order-sm-9{-ms-flex-order:9;order:9}.order-sm-10{-ms-flex-order:10;order:10}.order-sm-11{-ms-flex-order:11;order:11}.order-sm-12{-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;min-width:0;max-width:100%}.row-cols-md-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-md-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-md-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-md-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-md-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-md-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-md-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-ms-flex-order:-1;order:-1}.order-md-last{-ms-flex-order:13;order:13}.order-md-0{-ms-flex-order:0;order:0}.order-md-1{-ms-flex-order:1;order:1}.order-md-2{-ms-flex-order:2;order:2}.order-md-3{-ms-flex-order:3;order:3}.order-md-4{-ms-flex-order:4;order:4}.order-md-5{-ms-flex-order:5;order:5}.order-md-6{-ms-flex-order:6;order:6}.order-md-7{-ms-flex-order:7;order:7}.order-md-8{-ms-flex-order:8;order:8}.order-md-9{-ms-flex-order:9;order:9}.order-md-10{-ms-flex-order:10;order:10}.order-md-11{-ms-flex-order:11;order:11}.order-md-12{-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;min-width:0;max-width:100%}.row-cols-lg-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-lg-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-lg-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-lg-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-lg-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-lg-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-lg-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-ms-flex-order:-1;order:-1}.order-lg-last{-ms-flex-order:13;order:13}.order-lg-0{-ms-flex-order:0;order:0}.order-lg-1{-ms-flex-order:1;order:1}.order-lg-2{-ms-flex-order:2;order:2}.order-lg-3{-ms-flex-order:3;order:3}.order-lg-4{-ms-flex-order:4;order:4}.order-lg-5{-ms-flex-order:5;order:5}.order-lg-6{-ms-flex-order:6;order:6}.order-lg-7{-ms-flex-order:7;order:7}.order-lg-8{-ms-flex-order:8;order:8}.order-lg-9{-ms-flex-order:9;order:9}.order-lg-10{-ms-flex-order:10;order:10}.order-lg-11{-ms-flex-order:11;order:11}.order-lg-12{-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;min-width:0;max-width:100%}.row-cols-xl-1>*{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.row-cols-xl-2>*{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.row-cols-xl-3>*{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.row-cols-xl-4>*{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.row-cols-xl-5>*{-ms-flex:0 0 20%;flex:0 0 20%;max-width:20%}.row-cols-xl-6>*{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:100%}.col-xl-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-ms-flex-order:-1;order:-1}.order-xl-last{-ms-flex-order:13;order:13}.order-xl-0{-ms-flex-order:0;order:0}.order-xl-1{-ms-flex-order:1;order:1}.order-xl-2{-ms-flex-order:2;order:2}.order-xl-3{-ms-flex-order:3;order:3}.order-xl-4{-ms-flex-order:4;order:4}.order-xl-5{-ms-flex-order:5;order:5}.order-xl-6{-ms-flex-order:6;order:6}.order-xl-7{-ms-flex-order:7;order:7}.order-xl-8{-ms-flex-order:8;order:8}.order-xl-9{-ms-flex-order:9;order:9}.order-xl-10{-ms-flex-order:10;order:10}.order-xl-11{-ms-flex-order:11;order:11}.order-xl-12{-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}.flex-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.flex-sm-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-sm-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-sm-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.flex-md-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-md-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-md-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.flex-lg-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-lg-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-lg-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-xl-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-xl-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}.m-0{margin:0!important}.mt-0,.my-0{margin-top:0!important}.mr-0,.mx-0{margin-right:0!important}.mb-0,.my-0{margin-bottom:0!important}.ml-0,.mx-0{margin-left:0!important}.m-1{margin:.25rem!important}.mt-1,.my-1{margin-top:.25rem!important}.mr-1,.mx-1{margin-right:.25rem!important}.mb-1,.my-1{margin-bottom:.25rem!important}.ml-1,.mx-1{margin-left:.25rem!important}.m-2{margin:.5rem!important}.mt-2,.my-2{margin-top:.5rem!important}.mr-2,.mx-2{margin-right:.5rem!important}.mb-2,.my-2{margin-bottom:.5rem!important}.ml-2,.mx-2{margin-left:.5rem!important}.m-3{margin:1rem!important}.mt-3,.my-3{margin-top:1rem!important}.mr-3,.mx-3{margin-right:1rem!important}.mb-3,.my-3{margin-bottom:1rem!important}.ml-3,.mx-3{margin-left:1rem!important}.m-4{margin:1.5rem!important}.mt-4,.my-4{margin-top:1.5rem!important}.mr-4,.mx-4{margin-right:1.5rem!important}.mb-4,.my-4{margin-bottom:1.5rem!important}.ml-4,.mx-4{margin-left:1.5rem!important}.m-5{margin:3rem!important}.mt-5,.my-5{margin-top:3rem!important}.mr-5,.mx-5{margin-right:3rem!important}.mb-5,.my-5{margin-bottom:3rem!important}.ml-5,.mx-5{margin-left:3rem!important}.p-0{padding:0!important}.pt-0,.py-0{padding-top:0!important}.pr-0,.px-0{padding-right:0!important}.pb-0,.py-0{padding-bottom:0!important}.pl-0,.px-0{padding-left:0!important}.p-1{padding:.25rem!important}.pt-1,.py-1{padding-top:.25rem!important}.pr-1,.px-1{padding-right:.25rem!important}.pb-1,.py-1{padding-bottom:.25rem!important}.pl-1,.px-1{padding-left:.25rem!important}.p-2{padding:.5rem!important}.pt-2,.py-2{padding-top:.5rem!important}.pr-2,.px-2{padding-right:.5rem!important}.pb-2,.py-2{padding-bottom:.5rem!important}.pl-2,.px-2{padding-left:.5rem!important}.p-3{padding:1rem!important}.pt-3,.py-3{padding-top:1rem!important}.pr-3,.px-3{padding-right:1rem!important}.pb-3,.py-3{padding-bottom:1rem!important}.pl-3,.px-3{padding-left:1rem!important}.p-4{padding:1.5rem!important}.pt-4,.py-4{padding-top:1.5rem!important}.pr-4,.px-4{padding-right:1.5rem!important}.pb-4,.py-4{padding-bottom:1.5rem!important}.pl-4,.px-4{padding-left:1.5rem!important}.p-5{padding:3rem!important}.pt-5,.py-5{padding-top:3rem!important}.pr-5,.px-5{padding-right:3rem!important}.pb-5,.py-5{padding-bottom:3rem!important}.pl-5,.px-5{padding-left:3rem!important}.m-n1{margin:-.25rem!important}.mt-n1,.my-n1{margin-top:-.25rem!important}.mr-n1,.mx-n1{margin-right:-.25rem!important}.mb-n1,.my-n1{margin-bottom:-.25rem!important}.ml-n1,.mx-n1{margin-left:-.25rem!important}.m-n2{margin:-.5rem!important}.mt-n2,.my-n2{margin-top:-.5rem!important}.mr-n2,.mx-n2{margin-right:-.5rem!important}.mb-n2,.my-n2{margin-bottom:-.5rem!important}.ml-n2,.mx-n2{margin-left:-.5rem!important}.m-n3{margin:-1rem!important}.mt-n3,.my-n3{margin-top:-1rem!important}.mr-n3,.mx-n3{margin-right:-1rem!important}.mb-n3,.my-n3{margin-bottom:-1rem!important}.ml-n3,.mx-n3{margin-left:-1rem!important}.m-n4{margin:-1.5rem!important}.mt-n4,.my-n4{margin-top:-1.5rem!important}.mr-n4,.mx-n4{margin-right:-1.5rem!important}.mb-n4,.my-n4{margin-bottom:-1.5rem!important}.ml-n4,.mx-n4{margin-left:-1.5rem!important}.m-n5{margin:-3rem!important}.mt-n5,.my-n5{margin-top:-3rem!important}.mr-n5,.mx-n5{margin-right:-3rem!important}.mb-n5,.my-n5{margin-bottom:-3rem!important}.ml-n5,.mx-n5{margin-left:-3rem!important}.m-auto{margin:auto!important}.mt-auto,.my-auto{margin-top:auto!important}.mr-auto,.mx-auto{margin-right:auto!important}.mb-auto,.my-auto{margin-bottom:auto!important}.ml-auto,.mx-auto{margin-left:auto!important}@media (min-width:576px){.m-sm-0{margin:0!important}.mt-sm-0,.my-sm-0{margin-top:0!important}.mr-sm-0,.mx-sm-0{margin-right:0!important}.mb-sm-0,.my-sm-0{margin-bottom:0!important}.ml-sm-0,.mx-sm-0{margin-left:0!important}.m-sm-1{margin:.25rem!important}.mt-sm-1,.my-sm-1{margin-top:.25rem!important}.mr-sm-1,.mx-sm-1{margin-right:.25rem!important}.mb-sm-1,.my-sm-1{margin-bottom:.25rem!important}.ml-sm-1,.mx-sm-1{margin-left:.25rem!important}.m-sm-2{margin:.5rem!important}.mt-sm-2,.my-sm-2{margin-top:.5rem!important}.mr-sm-2,.mx-sm-2{margin-right:.5rem!important}.mb-sm-2,.my-sm-2{margin-bottom:.5rem!important}.ml-sm-2,.mx-sm-2{margin-left:.5rem!important}.m-sm-3{margin:1rem!important}.mt-sm-3,.my-sm-3{margin-top:1rem!important}.mr-sm-3,.mx-sm-3{margin-right:1rem!important}.mb-sm-3,.my-sm-3{margin-bottom:1rem!important}.ml-sm-3,.mx-sm-3{margin-left:1rem!important}.m-sm-4{margin:1.5rem!important}.mt-sm-4,.my-sm-4{margin-top:1.5rem!important}.mr-sm-4,.mx-sm-4{margin-right:1.5rem!important}.mb-sm-4,.my-sm-4{margin-bottom:1.5rem!important}.ml-sm-4,.mx-sm-4{margin-left:1.5rem!important}.m-sm-5{margin:3rem!important}.mt-sm-5,.my-sm-5{margin-top:3rem!important}.mr-sm-5,.mx-sm-5{margin-right:3rem!important}.mb-sm-5,.my-sm-5{margin-bottom:3rem!important}.ml-sm-5,.mx-sm-5{margin-left:3rem!important}.p-sm-0{padding:0!important}.pt-sm-0,.py-sm-0{padding-top:0!important}.pr-sm-0,.px-sm-0{padding-right:0!important}.pb-sm-0,.py-sm-0{padding-bottom:0!important}.pl-sm-0,.px-sm-0{padding-left:0!important}.p-sm-1{padding:.25rem!important}.pt-sm-1,.py-sm-1{padding-top:.25rem!important}.pr-sm-1,.px-sm-1{padding-right:.25rem!important}.pb-sm-1,.py-sm-1{padding-bottom:.25rem!important}.pl-sm-1,.px-sm-1{padding-left:.25rem!important}.p-sm-2{padding:.5rem!important}.pt-sm-2,.py-sm-2{padding-top:.5rem!important}.pr-sm-2,.px-sm-2{padding-right:.5rem!important}.pb-sm-2,.py-sm-2{padding-bottom:.5rem!important}.pl-sm-2,.px-sm-2{padding-left:.5rem!important}.p-sm-3{padding:1rem!important}.pt-sm-3,.py-sm-3{padding-top:1rem!important}.pr-sm-3,.px-sm-3{padding-right:1rem!important}.pb-sm-3,.py-sm-3{padding-bottom:1rem!important}.pl-sm-3,.px-sm-3{padding-left:1rem!important}.p-sm-4{padding:1.5rem!important}.pt-sm-4,.py-sm-4{padding-top:1.5rem!important}.pr-sm-4,.px-sm-4{padding-right:1.5rem!important}.pb-sm-4,.py-sm-4{padding-bottom:1.5rem!important}.pl-sm-4,.px-sm-4{padding-left:1.5rem!important}.p-sm-5{padding:3rem!important}.pt-sm-5,.py-sm-5{padding-top:3rem!important}.pr-sm-5,.px-sm-5{padding-right:3rem!important}.pb-sm-5,.py-sm-5{padding-bottom:3rem!important}.pl-sm-5,.px-sm-5{padding-left:3rem!important}.m-sm-n1{margin:-.25rem!important}.mt-sm-n1,.my-sm-n1{margin-top:-.25rem!important}.mr-sm-n1,.mx-sm-n1{margin-right:-.25rem!important}.mb-sm-n1,.my-sm-n1{margin-bottom:-.25rem!important}.ml-sm-n1,.mx-sm-n1{margin-left:-.25rem!important}.m-sm-n2{margin:-.5rem!important}.mt-sm-n2,.my-sm-n2{margin-top:-.5rem!important}.mr-sm-n2,.mx-sm-n2{margin-right:-.5rem!important}.mb-sm-n2,.my-sm-n2{margin-bottom:-.5rem!important}.ml-sm-n2,.mx-sm-n2{margin-left:-.5rem!important}.m-sm-n3{margin:-1rem!important}.mt-sm-n3,.my-sm-n3{margin-top:-1rem!important}.mr-sm-n3,.mx-sm-n3{margin-right:-1rem!important}.mb-sm-n3,.my-sm-n3{margin-bottom:-1rem!important}.ml-sm-n3,.mx-sm-n3{margin-left:-1rem!important}.m-sm-n4{margin:-1.5rem!important}.mt-sm-n4,.my-sm-n4{margin-top:-1.5rem!important}.mr-sm-n4,.mx-sm-n4{margin-right:-1.5rem!important}.mb-sm-n4,.my-sm-n4{margin-bottom:-1.5rem!important}.ml-sm-n4,.mx-sm-n4{margin-left:-1.5rem!important}.m-sm-n5{margin:-3rem!important}.mt-sm-n5,.my-sm-n5{margin-top:-3rem!important}.mr-sm-n5,.mx-sm-n5{margin-right:-3rem!important}.mb-sm-n5,.my-sm-n5{margin-bottom:-3rem!important}.ml-sm-n5,.mx-sm-n5{margin-left:-3rem!important}.m-sm-auto{margin:auto!important}.mt-sm-auto,.my-sm-auto{margin-top:auto!important}.mr-sm-auto,.mx-sm-auto{margin-right:auto!important}.mb-sm-auto,.my-sm-auto{margin-bottom:auto!important}.ml-sm-auto,.mx-sm-auto{margin-left:auto!important}}@media (min-width:768px){.m-md-0{margin:0!important}.mt-md-0,.my-md-0{margin-top:0!important}.mr-md-0,.mx-md-0{margin-right:0!important}.mb-md-0,.my-md-0{margin-bottom:0!important}.ml-md-0,.mx-md-0{margin-left:0!important}.m-md-1{margin:.25rem!important}.mt-md-1,.my-md-1{margin-top:.25rem!important}.mr-md-1,.mx-md-1{margin-right:.25rem!important}.mb-md-1,.my-md-1{margin-bottom:.25rem!important}.ml-md-1,.mx-md-1{margin-left:.25rem!important}.m-md-2{margin:.5rem!important}.mt-md-2,.my-md-2{margin-top:.5rem!important}.mr-md-2,.mx-md-2{margin-right:.5rem!important}.mb-md-2,.my-md-2{margin-bottom:.5rem!important}.ml-md-2,.mx-md-2{margin-left:.5rem!important}.m-md-3{margin:1rem!important}.mt-md-3,.my-md-3{margin-top:1rem!important}.mr-md-3,.mx-md-3{margin-right:1rem!important}.mb-md-3,.my-md-3{margin-bottom:1rem!important}.ml-md-3,.mx-md-3{margin-left:1rem!important}.m-md-4{margin:1.5rem!important}.mt-md-4,.my-md-4{margin-top:1.5rem!important}.mr-md-4,.mx-md-4{margin-right:1.5rem!important}.mb-md-4,.my-md-4{margin-bottom:1.5rem!important}.ml-md-4,.mx-md-4{margin-left:1.5rem!important}.m-md-5{margin:3rem!important}.mt-md-5,.my-md-5{margin-top:3rem!important}.mr-md-5,.mx-md-5{margin-right:3rem!important}.mb-md-5,.my-md-5{margin-bottom:3rem!important}.ml-md-5,.mx-md-5{margin-left:3rem!important}.p-md-0{padding:0!important}.pt-md-0,.py-md-0{padding-top:0!important}.pr-md-0,.px-md-0{padding-right:0!important}.pb-md-0,.py-md-0{padding-bottom:0!important}.pl-md-0,.px-md-0{padding-left:0!important}.p-md-1{padding:.25rem!important}.pt-md-1,.py-md-1{padding-top:.25rem!important}.pr-md-1,.px-md-1{padding-right:.25rem!important}.pb-md-1,.py-md-1{padding-bottom:.25rem!important}.pl-md-1,.px-md-1{padding-left:.25rem!important}.p-md-2{padding:.5rem!important}.pt-md-2,.py-md-2{padding-top:.5rem!important}.pr-md-2,.px-md-2{padding-right:.5rem!important}.pb-md-2,.py-md-2{padding-bottom:.5rem!important}.pl-md-2,.px-md-2{padding-left:.5rem!important}.p-md-3{padding:1rem!important}.pt-md-3,.py-md-3{padding-top:1rem!important}.pr-md-3,.px-md-3{padding-right:1rem!important}.pb-md-3,.py-md-3{padding-bottom:1rem!important}.pl-md-3,.px-md-3{padding-left:1rem!important}.p-md-4{padding:1.5rem!important}.pt-md-4,.py-md-4{padding-top:1.5rem!important}.pr-md-4,.px-md-4{padding-right:1.5rem!important}.pb-md-4,.py-md-4{padding-bottom:1.5rem!important}.pl-md-4,.px-md-4{padding-left:1.5rem!important}.p-md-5{padding:3rem!important}.pt-md-5,.py-md-5{padding-top:3rem!important}.pr-md-5,.px-md-5{padding-right:3rem!important}.pb-md-5,.py-md-5{padding-bottom:3rem!important}.pl-md-5,.px-md-5{padding-left:3rem!important}.m-md-n1{margin:-.25rem!important}.mt-md-n1,.my-md-n1{margin-top:-.25rem!important}.mr-md-n1,.mx-md-n1{margin-right:-.25rem!important}.mb-md-n1,.my-md-n1{margin-bottom:-.25rem!important}.ml-md-n1,.mx-md-n1{margin-left:-.25rem!important}.m-md-n2{margin:-.5rem!important}.mt-md-n2,.my-md-n2{margin-top:-.5rem!important}.mr-md-n2,.mx-md-n2{margin-right:-.5rem!important}.mb-md-n2,.my-md-n2{margin-bottom:-.5rem!important}.ml-md-n2,.mx-md-n2{margin-left:-.5rem!important}.m-md-n3{margin:-1rem!important}.mt-md-n3,.my-md-n3{margin-top:-1rem!important}.mr-md-n3,.mx-md-n3{margin-right:-1rem!important}.mb-md-n3,.my-md-n3{margin-bottom:-1rem!important}.ml-md-n3,.mx-md-n3{margin-left:-1rem!important}.m-md-n4{margin:-1.5rem!important}.mt-md-n4,.my-md-n4{margin-top:-1.5rem!important}.mr-md-n4,.mx-md-n4{margin-right:-1.5rem!important}.mb-md-n4,.my-md-n4{margin-bottom:-1.5rem!important}.ml-md-n4,.mx-md-n4{margin-left:-1.5rem!important}.m-md-n5{margin:-3rem!important}.mt-md-n5,.my-md-n5{margin-top:-3rem!important}.mr-md-n5,.mx-md-n5{margin-right:-3rem!important}.mb-md-n5,.my-md-n5{margin-bottom:-3rem!important}.ml-md-n5,.mx-md-n5{margin-left:-3rem!important}.m-md-auto{margin:auto!important}.mt-md-auto,.my-md-auto{margin-top:auto!important}.mr-md-auto,.mx-md-auto{margin-right:auto!important}.mb-md-auto,.my-md-auto{margin-bottom:auto!important}.ml-md-auto,.mx-md-auto{margin-left:auto!important}}@media (min-width:992px){.m-lg-0{margin:0!important}.mt-lg-0,.my-lg-0{margin-top:0!important}.mr-lg-0,.mx-lg-0{margin-right:0!important}.mb-lg-0,.my-lg-0{margin-bottom:0!important}.ml-lg-0,.mx-lg-0{margin-left:0!important}.m-lg-1{margin:.25rem!important}.mt-lg-1,.my-lg-1{margin-top:.25rem!important}.mr-lg-1,.mx-lg-1{margin-right:.25rem!important}.mb-lg-1,.my-lg-1{margin-bottom:.25rem!important}.ml-lg-1,.mx-lg-1{margin-left:.25rem!important}.m-lg-2{margin:.5rem!important}.mt-lg-2,.my-lg-2{margin-top:.5rem!important}.mr-lg-2,.mx-lg-2{margin-right:.5rem!important}.mb-lg-2,.my-lg-2{margin-bottom:.5rem!important}.ml-lg-2,.mx-lg-2{margin-left:.5rem!important}.m-lg-3{margin:1rem!important}.mt-lg-3,.my-lg-3{margin-top:1rem!important}.mr-lg-3,.mx-lg-3{margin-right:1rem!important}.mb-lg-3,.my-lg-3{margin-bottom:1rem!important}.ml-lg-3,.mx-lg-3{margin-left:1rem!important}.m-lg-4{margin:1.5rem!important}.mt-lg-4,.my-lg-4{margin-top:1.5rem!important}.mr-lg-4,.mx-lg-4{margin-right:1.5rem!important}.mb-lg-4,.my-lg-4{margin-bottom:1.5rem!important}.ml-lg-4,.mx-lg-4{margin-left:1.5rem!important}.m-lg-5{margin:3rem!important}.mt-lg-5,.my-lg-5{margin-top:3rem!important}.mr-lg-5,.mx-lg-5{margin-right:3rem!important}.mb-lg-5,.my-lg-5{margin-bottom:3rem!important}.ml-lg-5,.mx-lg-5{margin-left:3rem!important}.p-lg-0{padding:0!important}.pt-lg-0,.py-lg-0{padding-top:0!important}.pr-lg-0,.px-lg-0{padding-right:0!important}.pb-lg-0,.py-lg-0{padding-bottom:0!important}.pl-lg-0,.px-lg-0{padding-left:0!important}.p-lg-1{padding:.25rem!important}.pt-lg-1,.py-lg-1{padding-top:.25rem!important}.pr-lg-1,.px-lg-1{padding-right:.25rem!important}.pb-lg-1,.py-lg-1{padding-bottom:.25rem!important}.pl-lg-1,.px-lg-1{padding-left:.25rem!important}.p-lg-2{padding:.5rem!important}.pt-lg-2,.py-lg-2{padding-top:.5rem!important}.pr-lg-2,.px-lg-2{padding-right:.5rem!important}.pb-lg-2,.py-lg-2{padding-bottom:.5rem!important}.pl-lg-2,.px-lg-2{padding-left:.5rem!important}.p-lg-3{padding:1rem!important}.pt-lg-3,.py-lg-3{padding-top:1rem!important}.pr-lg-3,.px-lg-3{padding-right:1rem!important}.pb-lg-3,.py-lg-3{padding-bottom:1rem!important}.pl-lg-3,.px-lg-3{padding-left:1rem!important}.p-lg-4{padding:1.5rem!important}.pt-lg-4,.py-lg-4{padding-top:1.5rem!important}.pr-lg-4,.px-lg-4{padding-right:1.5rem!important}.pb-lg-4,.py-lg-4{padding-bottom:1.5rem!important}.pl-lg-4,.px-lg-4{padding-left:1.5rem!important}.p-lg-5{padding:3rem!important}.pt-lg-5,.py-lg-5{padding-top:3rem!important}.pr-lg-5,.px-lg-5{padding-right:3rem!important}.pb-lg-5,.py-lg-5{padding-bottom:3rem!important}.pl-lg-5,.px-lg-5{padding-left:3rem!important}.m-lg-n1{margin:-.25rem!important}.mt-lg-n1,.my-lg-n1{margin-top:-.25rem!important}.mr-lg-n1,.mx-lg-n1{margin-right:-.25rem!important}.mb-lg-n1,.my-lg-n1{margin-bottom:-.25rem!important}.ml-lg-n1,.mx-lg-n1{margin-left:-.25rem!important}.m-lg-n2{margin:-.5rem!important}.mt-lg-n2,.my-lg-n2{margin-top:-.5rem!important}.mr-lg-n2,.mx-lg-n2{margin-right:-.5rem!important}.mb-lg-n2,.my-lg-n2{margin-bottom:-.5rem!important}.ml-lg-n2,.mx-lg-n2{margin-left:-.5rem!important}.m-lg-n3{margin:-1rem!important}.mt-lg-n3,.my-lg-n3{margin-top:-1rem!important}.mr-lg-n3,.mx-lg-n3{margin-right:-1rem!important}.mb-lg-n3,.my-lg-n3{margin-bottom:-1rem!important}.ml-lg-n3,.mx-lg-n3{margin-left:-1rem!important}.m-lg-n4{margin:-1.5rem!important}.mt-lg-n4,.my-lg-n4{margin-top:-1.5rem!important}.mr-lg-n4,.mx-lg-n4{margin-right:-1.5rem!important}.mb-lg-n4,.my-lg-n4{margin-bottom:-1.5rem!important}.ml-lg-n4,.mx-lg-n4{margin-left:-1.5rem!important}.m-lg-n5{margin:-3rem!important}.mt-lg-n5,.my-lg-n5{margin-top:-3rem!important}.mr-lg-n5,.mx-lg-n5{margin-right:-3rem!important}.mb-lg-n5,.my-lg-n5{margin-bottom:-3rem!important}.ml-lg-n5,.mx-lg-n5{margin-left:-3rem!important}.m-lg-auto{margin:auto!important}.mt-lg-auto,.my-lg-auto{margin-top:auto!important}.mr-lg-auto,.mx-lg-auto{margin-right:auto!important}.mb-lg-auto,.my-lg-auto{margin-bottom:auto!important}.ml-lg-auto,.mx-lg-auto{margin-left:auto!important}}@media (min-width:1200px){.m-xl-0{margin:0!important}.mt-xl-0,.my-xl-0{margin-top:0!important}.mr-xl-0,.mx-xl-0{margin-right:0!important}.mb-xl-0,.my-xl-0{margin-bottom:0!important}.ml-xl-0,.mx-xl-0{margin-left:0!important}.m-xl-1{margin:.25rem!important}.mt-xl-1,.my-xl-1{margin-top:.25rem!important}.mr-xl-1,.mx-xl-1{margin-right:.25rem!important}.mb-xl-1,.my-xl-1{margin-bottom:.25rem!important}.ml-xl-1,.mx-xl-1{margin-left:.25rem!important}.m-xl-2{margin:.5rem!important}.mt-xl-2,.my-xl-2{margin-top:.5rem!important}.mr-xl-2,.mx-xl-2{margin-right:.5rem!important}.mb-xl-2,.my-xl-2{margin-bottom:.5rem!important}.ml-xl-2,.mx-xl-2{margin-left:.5rem!important}.m-xl-3{margin:1rem!important}.mt-xl-3,.my-xl-3{margin-top:1rem!important}.mr-xl-3,.mx-xl-3{margin-right:1rem!important}.mb-xl-3,.my-xl-3{margin-bottom:1rem!important}.ml-xl-3,.mx-xl-3{margin-left:1rem!important}.m-xl-4{margin:1.5rem!important}.mt-xl-4,.my-xl-4{margin-top:1.5rem!important}.mr-xl-4,.mx-xl-4{margin-right:1.5rem!important}.mb-xl-4,.my-xl-4{margin-bottom:1.5rem!important}.ml-xl-4,.mx-xl-4{margin-left:1.5rem!important}.m-xl-5{margin:3rem!important}.mt-xl-5,.my-xl-5{margin-top:3rem!important}.mr-xl-5,.mx-xl-5{margin-right:3rem!important}.mb-xl-5,.my-xl-5{margin-bottom:3rem!important}.ml-xl-5,.mx-xl-5{margin-left:3rem!important}.p-xl-0{padding:0!important}.pt-xl-0,.py-xl-0{padding-top:0!important}.pr-xl-0,.px-xl-0{padding-right:0!important}.pb-xl-0,.py-xl-0{padding-bottom:0!important}.pl-xl-0,.px-xl-0{padding-left:0!important}.p-xl-1{padding:.25rem!important}.pt-xl-1,.py-xl-1{padding-top:.25rem!important}.pr-xl-1,.px-xl-1{padding-right:.25rem!important}.pb-xl-1,.py-xl-1{padding-bottom:.25rem!important}.pl-xl-1,.px-xl-1{padding-left:.25rem!important}.p-xl-2{padding:.5rem!important}.pt-xl-2,.py-xl-2{padding-top:.5rem!important}.pr-xl-2,.px-xl-2{padding-right:.5rem!important}.pb-xl-2,.py-xl-2{padding-bottom:.5rem!important}.pl-xl-2,.px-xl-2{padding-left:.5rem!important}.p-xl-3{padding:1rem!important}.pt-xl-3,.py-xl-3{padding-top:1rem!important}.pr-xl-3,.px-xl-3{padding-right:1rem!important}.pb-xl-3,.py-xl-3{padding-bottom:1rem!important}.pl-xl-3,.px-xl-3{padding-left:1rem!important}.p-xl-4{padding:1.5rem!important}.pt-xl-4,.py-xl-4{padding-top:1.5rem!important}.pr-xl-4,.px-xl-4{padding-right:1.5rem!important}.pb-xl-4,.py-xl-4{padding-bottom:1.5rem!important}.pl-xl-4,.px-xl-4{padding-left:1.5rem!important}.p-xl-5{padding:3rem!important}.pt-xl-5,.py-xl-5{padding-top:3rem!important}.pr-xl-5,.px-xl-5{padding-right:3rem!important}.pb-xl-5,.py-xl-5{padding-bottom:3rem!important}.pl-xl-5,.px-xl-5{padding-left:3rem!important}.m-xl-n1{margin:-.25rem!important}.mt-xl-n1,.my-xl-n1{margin-top:-.25rem!important}.mr-xl-n1,.mx-xl-n1{margin-right:-.25rem!important}.mb-xl-n1,.my-xl-n1{margin-bottom:-.25rem!important}.ml-xl-n1,.mx-xl-n1{margin-left:-.25rem!important}.m-xl-n2{margin:-.5rem!important}.mt-xl-n2,.my-xl-n2{margin-top:-.5rem!important}.mr-xl-n2,.mx-xl-n2{margin-right:-.5rem!important}.mb-xl-n2,.my-xl-n2{margin-bottom:-.5rem!important}.ml-xl-n2,.mx-xl-n2{margin-left:-.5rem!important}.m-xl-n3{margin:-1rem!important}.mt-xl-n3,.my-xl-n3{margin-top:-1rem!important}.mr-xl-n3,.mx-xl-n3{margin-right:-1rem!important}.mb-xl-n3,.my-xl-n3{margin-bottom:-1rem!important}.ml-xl-n3,.mx-xl-n3{margin-left:-1rem!important}.m-xl-n4{margin:-1.5rem!important}.mt-xl-n4,.my-xl-n4{margin-top:-1.5rem!important}.mr-xl-n4,.mx-xl-n4{margin-right:-1.5rem!important}.mb-xl-n4,.my-xl-n4{margin-bottom:-1.5rem!important}.ml-xl-n4,.mx-xl-n4{margin-left:-1.5rem!important}.m-xl-n5{margin:-3rem!important}.mt-xl-n5,.my-xl-n5{margin-top:-3rem!important}.mr-xl-n5,.mx-xl-n5{margin-right:-3rem!important}.mb-xl-n5,.my-xl-n5{margin-bottom:-3rem!important}.ml-xl-n5,.mx-xl-n5{margin-left:-3rem!important}.m-xl-auto{margin:auto!important}.mt-xl-auto,.my-xl-auto{margin-top:auto!important}.mr-xl-auto,.mx-xl-auto{margin-right:auto!important}.mb-xl-auto,.my-xl-auto{margin-bottom:auto!important}.ml-xl-auto,.mx-xl-auto{margin-left:auto!important}} +/*# sourceMappingURL=bootstrap-grid.min.css.map */ \ No newline at end of file diff --git a/assets/ext/bootstrap/css/bootstrap-grid.min.css.map b/assets/ext/bootstrap/css/bootstrap-grid.min.css.map new file mode 100644 index 00000000..61322424 --- /dev/null +++ b/assets/ext/bootstrap/css/bootstrap-grid.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../scss/bootstrap-grid.scss","dist/css/bootstrap-grid.css","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/mixins/_breakpoints.scss","../../scss/mixins/_grid-framework.scss","../../scss/utilities/_display.scss","../../scss/utilities/_flex.scss","../../scss/utilities/_spacing.scss"],"names":[],"mappings":"AAAA;;;;;AAOA,KACE,WAAA,WACA,mBAAA,UAGF,ECCA,QADA,SDGE,WAAA,QETA,WCDA,MAAA,KACA,cAAA,KACA,aAAA,KACA,aAAA,KACA,YAAA,KCmDE,yBFtDF,WCWI,UAAA,OC2CF,yBFtDF,WCWI,UAAA,OC2CF,yBFtDF,WCWI,UAAA,OC2CF,0BFtDF,WCWI,UAAA,QDLJ,iBAAA,cAAA,cAAA,cAAA,cCPA,MAAA,KACA,cAAA,KACA,aAAA,KACA,aAAA,KACA,YAAA,KCmDE,yBFrCE,WAAA,cACE,UAAA,OEoCJ,yBFrCE,WAAA,cAAA,cACE,UAAA,OEoCJ,yBFrCE,WAAA,cAAA,cAAA,cACE,UAAA,OEoCJ,0BFrCE,WAAA,cAAA,cAAA,cAAA,cACE,UAAA,QA4BN,KC7BA,QAAA,YAAA,QAAA,KACA,cAAA,KAAA,UAAA,KACA,aAAA,MACA,YAAA,MDgCA,YACE,aAAA,EACA,YAAA,EAFF,iBDsCF,0BChCM,cAAA,EACA,aAAA,EG1DJ,KAAA,OAAA,QAAA,QAAA,QAAA,OAAA,OAAA,OAAA,OAAA,OAAA,OAAA,OAAA,OJ+FF,UAEqJ,QAAvI,UAAmG,WAAY,WAAY,WAAhH,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,UACtG,aAFqJ,QAAvI,UAAmG,WAAY,WAAY,WAAhH,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,UACtG,aAFkJ,QAAvI,UAAmG,WAAY,WAAY,WAAhH,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,UACnG,aAEqJ,QAAvI,UAAmG,WAAY,WAAY,WAAhH,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,UACtG,aIlGI,SAAA,SACA,MAAA,KACA,cAAA,KACA,aAAA,KAsBE,KACE,wBAAA,EAAA,WAAA,EACA,kBAAA,EAAA,UAAA,EACA,UAAA,EACA,UAAA,KAKE,cFuBN,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,UAAA,KExBM,cFuBN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IACA,UAAA,IExBM,cFuBN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WACA,UAAA,WExBM,cFuBN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IACA,UAAA,IExBM,cFuBN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IACA,UAAA,IExBM,cFuBN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WACA,UAAA,WElBE,UFAJ,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,MAAA,KACA,UAAA,KEIQ,OFdR,SAAA,EAAA,EAAA,UAAA,KAAA,EAAA,EAAA,UAIA,UAAA,UEUQ,OFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,OFdR,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEUQ,OFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,OFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,OFdR,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEUQ,OFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,OFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,OFdR,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEUQ,QFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,QFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,QFdR,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KAIA,UAAA,KEgBI,aAAwB,eAAA,GAAA,MAAA,GAExB,YAAuB,eAAA,GAAA,MAAA,GAGrB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,UAAwB,eAAA,GAAA,MAAA,GAAxB,UAAwB,eAAA,GAAA,MAAA,GAAxB,UAAwB,eAAA,GAAA,MAAA,GAOpB,UFjBV,YAAA,UEiBU,UFjBV,YAAA,WEiBU,UFjBV,YAAA,IEiBU,UFjBV,YAAA,WEiBU,UFjBV,YAAA,WEiBU,UFjBV,YAAA,IEiBU,UFjBV,YAAA,WEiBU,UFjBV,YAAA,WEiBU,UFjBV,YAAA,IEiBU,WFjBV,YAAA,WEiBU,WFjBV,YAAA,WCKE,yBC3BE,QACE,wBAAA,EAAA,WAAA,EACA,kBAAA,EAAA,UAAA,EACA,UAAA,EACA,UAAA,KAKE,iBFuBN,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,UAAA,KExBM,iBFuBN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IACA,UAAA,IExBM,iBFuBN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WACA,UAAA,WExBM,iBFuBN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IACA,UAAA,IExBM,iBFuBN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IACA,UAAA,IExBM,iBFuBN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WACA,UAAA,WElBE,aFAJ,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,MAAA,KACA,UAAA,KEIQ,UFdR,SAAA,EAAA,EAAA,UAAA,KAAA,EAAA,EAAA,UAIA,UAAA,UEUQ,UFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,UFdR,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEUQ,UFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,UFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,UFdR,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEUQ,UFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,UFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,UFdR,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEUQ,WFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,WFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,WFdR,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KAIA,UAAA,KEgBI,gBAAwB,eAAA,GAAA,MAAA,GAExB,eAAuB,eAAA,GAAA,MAAA,GAGrB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,aAAwB,eAAA,GAAA,MAAA,GAAxB,aAAwB,eAAA,GAAA,MAAA,GAAxB,aAAwB,eAAA,GAAA,MAAA,GAOpB,aFjBV,YAAA,EEiBU,aFjBV,YAAA,UEiBU,aFjBV,YAAA,WEiBU,aFjBV,YAAA,IEiBU,aFjBV,YAAA,WEiBU,aFjBV,YAAA,WEiBU,aFjBV,YAAA,IEiBU,aFjBV,YAAA,WEiBU,aFjBV,YAAA,WEiBU,aFjBV,YAAA,IEiBU,cFjBV,YAAA,WEiBU,cFjBV,YAAA,YCKE,yBC3BE,QACE,wBAAA,EAAA,WAAA,EACA,kBAAA,EAAA,UAAA,EACA,UAAA,EACA,UAAA,KAKE,iBFuBN,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,UAAA,KExBM,iBFuBN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IACA,UAAA,IExBM,iBFuBN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WACA,UAAA,WExBM,iBFuBN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IACA,UAAA,IExBM,iBFuBN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IACA,UAAA,IExBM,iBFuBN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WACA,UAAA,WElBE,aFAJ,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,MAAA,KACA,UAAA,KEIQ,UFdR,SAAA,EAAA,EAAA,UAAA,KAAA,EAAA,EAAA,UAIA,UAAA,UEUQ,UFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,UFdR,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEUQ,UFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,UFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,UFdR,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEUQ,UFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,UFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,UFdR,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEUQ,WFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,WFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,WFdR,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KAIA,UAAA,KEgBI,gBAAwB,eAAA,GAAA,MAAA,GAExB,eAAuB,eAAA,GAAA,MAAA,GAGrB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,aAAwB,eAAA,GAAA,MAAA,GAAxB,aAAwB,eAAA,GAAA,MAAA,GAAxB,aAAwB,eAAA,GAAA,MAAA,GAOpB,aFjBV,YAAA,EEiBU,aFjBV,YAAA,UEiBU,aFjBV,YAAA,WEiBU,aFjBV,YAAA,IEiBU,aFjBV,YAAA,WEiBU,aFjBV,YAAA,WEiBU,aFjBV,YAAA,IEiBU,aFjBV,YAAA,WEiBU,aFjBV,YAAA,WEiBU,aFjBV,YAAA,IEiBU,cFjBV,YAAA,WEiBU,cFjBV,YAAA,YCKE,yBC3BE,QACE,wBAAA,EAAA,WAAA,EACA,kBAAA,EAAA,UAAA,EACA,UAAA,EACA,UAAA,KAKE,iBFuBN,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,UAAA,KExBM,iBFuBN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IACA,UAAA,IExBM,iBFuBN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WACA,UAAA,WExBM,iBFuBN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IACA,UAAA,IExBM,iBFuBN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IACA,UAAA,IExBM,iBFuBN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WACA,UAAA,WElBE,aFAJ,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,MAAA,KACA,UAAA,KEIQ,UFdR,SAAA,EAAA,EAAA,UAAA,KAAA,EAAA,EAAA,UAIA,UAAA,UEUQ,UFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,UFdR,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEUQ,UFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,UFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,UFdR,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEUQ,UFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,UFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,UFdR,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEUQ,WFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,WFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,WFdR,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KAIA,UAAA,KEgBI,gBAAwB,eAAA,GAAA,MAAA,GAExB,eAAuB,eAAA,GAAA,MAAA,GAGrB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,aAAwB,eAAA,GAAA,MAAA,GAAxB,aAAwB,eAAA,GAAA,MAAA,GAAxB,aAAwB,eAAA,GAAA,MAAA,GAOpB,aFjBV,YAAA,EEiBU,aFjBV,YAAA,UEiBU,aFjBV,YAAA,WEiBU,aFjBV,YAAA,IEiBU,aFjBV,YAAA,WEiBU,aFjBV,YAAA,WEiBU,aFjBV,YAAA,IEiBU,aFjBV,YAAA,WEiBU,aFjBV,YAAA,WEiBU,aFjBV,YAAA,IEiBU,cFjBV,YAAA,WEiBU,cFjBV,YAAA,YCKE,0BC3BE,QACE,wBAAA,EAAA,WAAA,EACA,kBAAA,EAAA,UAAA,EACA,UAAA,EACA,UAAA,KAKE,iBFuBN,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,UAAA,KExBM,iBFuBN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IACA,UAAA,IExBM,iBFuBN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WACA,UAAA,WExBM,iBFuBN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IACA,UAAA,IExBM,iBFuBN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IACA,UAAA,IExBM,iBFuBN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WACA,UAAA,WElBE,aFAJ,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,MAAA,KACA,UAAA,KEIQ,UFdR,SAAA,EAAA,EAAA,UAAA,KAAA,EAAA,EAAA,UAIA,UAAA,UEUQ,UFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,UFdR,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEUQ,UFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,UFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,UFdR,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEUQ,UFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,UFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,UFdR,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEUQ,WFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,WFdR,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEUQ,WFdR,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KAIA,UAAA,KEgBI,gBAAwB,eAAA,GAAA,MAAA,GAExB,eAAuB,eAAA,GAAA,MAAA,GAGrB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,aAAwB,eAAA,GAAA,MAAA,GAAxB,aAAwB,eAAA,GAAA,MAAA,GAAxB,aAAwB,eAAA,GAAA,MAAA,GAOpB,aFjBV,YAAA,EEiBU,aFjBV,YAAA,UEiBU,aFjBV,YAAA,WEiBU,aFjBV,YAAA,IEiBU,aFjBV,YAAA,WEiBU,aFjBV,YAAA,WEiBU,aFjBV,YAAA,IEiBU,aFjBV,YAAA,WEiBU,aFjBV,YAAA,WEiBU,aFjBV,YAAA,IEiBU,cFjBV,YAAA,WEiBU,cFjBV,YAAA,YG5CI,QAAwB,QAAA,eAAxB,UAAwB,QAAA,iBAAxB,gBAAwB,QAAA,uBAAxB,SAAwB,QAAA,gBAAxB,SAAwB,QAAA,gBAAxB,aAAwB,QAAA,oBAAxB,cAAwB,QAAA,qBAAxB,QAAwB,QAAA,sBAAA,QAAA,eAAxB,eAAwB,QAAA,6BAAA,QAAA,sBFiD1B,yBEjDE,WAAwB,QAAA,eAAxB,aAAwB,QAAA,iBAAxB,mBAAwB,QAAA,uBAAxB,YAAwB,QAAA,gBAAxB,YAAwB,QAAA,gBAAxB,gBAAwB,QAAA,oBAAxB,iBAAwB,QAAA,qBAAxB,WAAwB,QAAA,sBAAA,QAAA,eAAxB,kBAAwB,QAAA,6BAAA,QAAA,uBFiD1B,yBEjDE,WAAwB,QAAA,eAAxB,aAAwB,QAAA,iBAAxB,mBAAwB,QAAA,uBAAxB,YAAwB,QAAA,gBAAxB,YAAwB,QAAA,gBAAxB,gBAAwB,QAAA,oBAAxB,iBAAwB,QAAA,qBAAxB,WAAwB,QAAA,sBAAA,QAAA,eAAxB,kBAAwB,QAAA,6BAAA,QAAA,uBFiD1B,yBEjDE,WAAwB,QAAA,eAAxB,aAAwB,QAAA,iBAAxB,mBAAwB,QAAA,uBAAxB,YAAwB,QAAA,gBAAxB,YAAwB,QAAA,gBAAxB,gBAAwB,QAAA,oBAAxB,iBAAwB,QAAA,qBAAxB,WAAwB,QAAA,sBAAA,QAAA,eAAxB,kBAAwB,QAAA,6BAAA,QAAA,uBFiD1B,0BEjDE,WAAwB,QAAA,eAAxB,aAAwB,QAAA,iBAAxB,mBAAwB,QAAA,uBAAxB,YAAwB,QAAA,gBAAxB,YAAwB,QAAA,gBAAxB,gBAAwB,QAAA,oBAAxB,iBAAwB,QAAA,qBAAxB,WAAwB,QAAA,sBAAA,QAAA,eAAxB,kBAAwB,QAAA,6BAAA,QAAA,uBAU9B,aAEI,cAAqB,QAAA,eAArB,gBAAqB,QAAA,iBAArB,sBAAqB,QAAA,uBAArB,eAAqB,QAAA,gBAArB,eAAqB,QAAA,gBAArB,mBAAqB,QAAA,oBAArB,oBAAqB,QAAA,qBAArB,cAAqB,QAAA,sBAAA,QAAA,eAArB,qBAAqB,QAAA,6BAAA,QAAA,uBCbrB,UAAgC,mBAAA,cAAA,eAAA,cAChC,aAAgC,mBAAA,iBAAA,eAAA,iBAChC,kBAAgC,mBAAA,sBAAA,eAAA,sBAChC,qBAAgC,mBAAA,yBAAA,eAAA,yBAEhC,WAA8B,cAAA,eAAA,UAAA,eAC9B,aAA8B,cAAA,iBAAA,UAAA,iBAC9B,mBAA8B,cAAA,uBAAA,UAAA,uBAC9B,WAA8B,SAAA,EAAA,EAAA,eAAA,KAAA,EAAA,EAAA,eAC9B,aAA8B,kBAAA,YAAA,UAAA,YAC9B,aAA8B,kBAAA,YAAA,UAAA,YAC9B,eAA8B,kBAAA,YAAA,YAAA,YAC9B,eAA8B,kBAAA,YAAA,YAAA,YAE9B,uBAAoC,cAAA,gBAAA,gBAAA,qBACpC,qBAAoC,cAAA,cAAA,gBAAA,mBACpC,wBAAoC,cAAA,iBAAA,gBAAA,iBACpC,yBAAoC,cAAA,kBAAA,gBAAA,wBACpC,wBAAoC,cAAA,qBAAA,gBAAA,uBAEpC,mBAAiC,eAAA,gBAAA,YAAA,qBACjC,iBAAiC,eAAA,cAAA,YAAA,mBACjC,oBAAiC,eAAA,iBAAA,YAAA,iBACjC,sBAAiC,eAAA,mBAAA,YAAA,mBACjC,qBAAiC,eAAA,kBAAA,YAAA,kBAEjC,qBAAkC,mBAAA,gBAAA,cAAA,qBAClC,mBAAkC,mBAAA,cAAA,cAAA,mBAClC,sBAAkC,mBAAA,iBAAA,cAAA,iBAClC,uBAAkC,mBAAA,kBAAA,cAAA,wBAClC,sBAAkC,mBAAA,qBAAA,cAAA,uBAClC,uBAAkC,mBAAA,kBAAA,cAAA,kBAElC,iBAAgC,oBAAA,eAAA,WAAA,eAChC,kBAAgC,oBAAA,gBAAA,WAAA,qBAChC,gBAAgC,oBAAA,cAAA,WAAA,mBAChC,mBAAgC,oBAAA,iBAAA,WAAA,iBAChC,qBAAgC,oBAAA,mBAAA,WAAA,mBAChC,oBAAgC,oBAAA,kBAAA,WAAA,kBHYhC,yBGlDA,aAAgC,mBAAA,cAAA,eAAA,cAChC,gBAAgC,mBAAA,iBAAA,eAAA,iBAChC,qBAAgC,mBAAA,sBAAA,eAAA,sBAChC,wBAAgC,mBAAA,yBAAA,eAAA,yBAEhC,cAA8B,cAAA,eAAA,UAAA,eAC9B,gBAA8B,cAAA,iBAAA,UAAA,iBAC9B,sBAA8B,cAAA,uBAAA,UAAA,uBAC9B,cAA8B,SAAA,EAAA,EAAA,eAAA,KAAA,EAAA,EAAA,eAC9B,gBAA8B,kBAAA,YAAA,UAAA,YAC9B,gBAA8B,kBAAA,YAAA,UAAA,YAC9B,kBAA8B,kBAAA,YAAA,YAAA,YAC9B,kBAA8B,kBAAA,YAAA,YAAA,YAE9B,0BAAoC,cAAA,gBAAA,gBAAA,qBACpC,wBAAoC,cAAA,cAAA,gBAAA,mBACpC,2BAAoC,cAAA,iBAAA,gBAAA,iBACpC,4BAAoC,cAAA,kBAAA,gBAAA,wBACpC,2BAAoC,cAAA,qBAAA,gBAAA,uBAEpC,sBAAiC,eAAA,gBAAA,YAAA,qBACjC,oBAAiC,eAAA,cAAA,YAAA,mBACjC,uBAAiC,eAAA,iBAAA,YAAA,iBACjC,yBAAiC,eAAA,mBAAA,YAAA,mBACjC,wBAAiC,eAAA,kBAAA,YAAA,kBAEjC,wBAAkC,mBAAA,gBAAA,cAAA,qBAClC,sBAAkC,mBAAA,cAAA,cAAA,mBAClC,yBAAkC,mBAAA,iBAAA,cAAA,iBAClC,0BAAkC,mBAAA,kBAAA,cAAA,wBAClC,yBAAkC,mBAAA,qBAAA,cAAA,uBAClC,0BAAkC,mBAAA,kBAAA,cAAA,kBAElC,oBAAgC,oBAAA,eAAA,WAAA,eAChC,qBAAgC,oBAAA,gBAAA,WAAA,qBAChC,mBAAgC,oBAAA,cAAA,WAAA,mBAChC,sBAAgC,oBAAA,iBAAA,WAAA,iBAChC,wBAAgC,oBAAA,mBAAA,WAAA,mBAChC,uBAAgC,oBAAA,kBAAA,WAAA,mBHYhC,yBGlDA,aAAgC,mBAAA,cAAA,eAAA,cAChC,gBAAgC,mBAAA,iBAAA,eAAA,iBAChC,qBAAgC,mBAAA,sBAAA,eAAA,sBAChC,wBAAgC,mBAAA,yBAAA,eAAA,yBAEhC,cAA8B,cAAA,eAAA,UAAA,eAC9B,gBAA8B,cAAA,iBAAA,UAAA,iBAC9B,sBAA8B,cAAA,uBAAA,UAAA,uBAC9B,cAA8B,SAAA,EAAA,EAAA,eAAA,KAAA,EAAA,EAAA,eAC9B,gBAA8B,kBAAA,YAAA,UAAA,YAC9B,gBAA8B,kBAAA,YAAA,UAAA,YAC9B,kBAA8B,kBAAA,YAAA,YAAA,YAC9B,kBAA8B,kBAAA,YAAA,YAAA,YAE9B,0BAAoC,cAAA,gBAAA,gBAAA,qBACpC,wBAAoC,cAAA,cAAA,gBAAA,mBACpC,2BAAoC,cAAA,iBAAA,gBAAA,iBACpC,4BAAoC,cAAA,kBAAA,gBAAA,wBACpC,2BAAoC,cAAA,qBAAA,gBAAA,uBAEpC,sBAAiC,eAAA,gBAAA,YAAA,qBACjC,oBAAiC,eAAA,cAAA,YAAA,mBACjC,uBAAiC,eAAA,iBAAA,YAAA,iBACjC,yBAAiC,eAAA,mBAAA,YAAA,mBACjC,wBAAiC,eAAA,kBAAA,YAAA,kBAEjC,wBAAkC,mBAAA,gBAAA,cAAA,qBAClC,sBAAkC,mBAAA,cAAA,cAAA,mBAClC,yBAAkC,mBAAA,iBAAA,cAAA,iBAClC,0BAAkC,mBAAA,kBAAA,cAAA,wBAClC,yBAAkC,mBAAA,qBAAA,cAAA,uBAClC,0BAAkC,mBAAA,kBAAA,cAAA,kBAElC,oBAAgC,oBAAA,eAAA,WAAA,eAChC,qBAAgC,oBAAA,gBAAA,WAAA,qBAChC,mBAAgC,oBAAA,cAAA,WAAA,mBAChC,sBAAgC,oBAAA,iBAAA,WAAA,iBAChC,wBAAgC,oBAAA,mBAAA,WAAA,mBAChC,uBAAgC,oBAAA,kBAAA,WAAA,mBHYhC,yBGlDA,aAAgC,mBAAA,cAAA,eAAA,cAChC,gBAAgC,mBAAA,iBAAA,eAAA,iBAChC,qBAAgC,mBAAA,sBAAA,eAAA,sBAChC,wBAAgC,mBAAA,yBAAA,eAAA,yBAEhC,cAA8B,cAAA,eAAA,UAAA,eAC9B,gBAA8B,cAAA,iBAAA,UAAA,iBAC9B,sBAA8B,cAAA,uBAAA,UAAA,uBAC9B,cAA8B,SAAA,EAAA,EAAA,eAAA,KAAA,EAAA,EAAA,eAC9B,gBAA8B,kBAAA,YAAA,UAAA,YAC9B,gBAA8B,kBAAA,YAAA,UAAA,YAC9B,kBAA8B,kBAAA,YAAA,YAAA,YAC9B,kBAA8B,kBAAA,YAAA,YAAA,YAE9B,0BAAoC,cAAA,gBAAA,gBAAA,qBACpC,wBAAoC,cAAA,cAAA,gBAAA,mBACpC,2BAAoC,cAAA,iBAAA,gBAAA,iBACpC,4BAAoC,cAAA,kBAAA,gBAAA,wBACpC,2BAAoC,cAAA,qBAAA,gBAAA,uBAEpC,sBAAiC,eAAA,gBAAA,YAAA,qBACjC,oBAAiC,eAAA,cAAA,YAAA,mBACjC,uBAAiC,eAAA,iBAAA,YAAA,iBACjC,yBAAiC,eAAA,mBAAA,YAAA,mBACjC,wBAAiC,eAAA,kBAAA,YAAA,kBAEjC,wBAAkC,mBAAA,gBAAA,cAAA,qBAClC,sBAAkC,mBAAA,cAAA,cAAA,mBAClC,yBAAkC,mBAAA,iBAAA,cAAA,iBAClC,0BAAkC,mBAAA,kBAAA,cAAA,wBAClC,yBAAkC,mBAAA,qBAAA,cAAA,uBAClC,0BAAkC,mBAAA,kBAAA,cAAA,kBAElC,oBAAgC,oBAAA,eAAA,WAAA,eAChC,qBAAgC,oBAAA,gBAAA,WAAA,qBAChC,mBAAgC,oBAAA,cAAA,WAAA,mBAChC,sBAAgC,oBAAA,iBAAA,WAAA,iBAChC,wBAAgC,oBAAA,mBAAA,WAAA,mBAChC,uBAAgC,oBAAA,kBAAA,WAAA,mBHYhC,0BGlDA,aAAgC,mBAAA,cAAA,eAAA,cAChC,gBAAgC,mBAAA,iBAAA,eAAA,iBAChC,qBAAgC,mBAAA,sBAAA,eAAA,sBAChC,wBAAgC,mBAAA,yBAAA,eAAA,yBAEhC,cAA8B,cAAA,eAAA,UAAA,eAC9B,gBAA8B,cAAA,iBAAA,UAAA,iBAC9B,sBAA8B,cAAA,uBAAA,UAAA,uBAC9B,cAA8B,SAAA,EAAA,EAAA,eAAA,KAAA,EAAA,EAAA,eAC9B,gBAA8B,kBAAA,YAAA,UAAA,YAC9B,gBAA8B,kBAAA,YAAA,UAAA,YAC9B,kBAA8B,kBAAA,YAAA,YAAA,YAC9B,kBAA8B,kBAAA,YAAA,YAAA,YAE9B,0BAAoC,cAAA,gBAAA,gBAAA,qBACpC,wBAAoC,cAAA,cAAA,gBAAA,mBACpC,2BAAoC,cAAA,iBAAA,gBAAA,iBACpC,4BAAoC,cAAA,kBAAA,gBAAA,wBACpC,2BAAoC,cAAA,qBAAA,gBAAA,uBAEpC,sBAAiC,eAAA,gBAAA,YAAA,qBACjC,oBAAiC,eAAA,cAAA,YAAA,mBACjC,uBAAiC,eAAA,iBAAA,YAAA,iBACjC,yBAAiC,eAAA,mBAAA,YAAA,mBACjC,wBAAiC,eAAA,kBAAA,YAAA,kBAEjC,wBAAkC,mBAAA,gBAAA,cAAA,qBAClC,sBAAkC,mBAAA,cAAA,cAAA,mBAClC,yBAAkC,mBAAA,iBAAA,cAAA,iBAClC,0BAAkC,mBAAA,kBAAA,cAAA,wBAClC,yBAAkC,mBAAA,qBAAA,cAAA,uBAClC,0BAAkC,mBAAA,kBAAA,cAAA,kBAElC,oBAAgC,oBAAA,eAAA,WAAA,eAChC,qBAAgC,oBAAA,gBAAA,WAAA,qBAChC,mBAAgC,oBAAA,cAAA,WAAA,mBAChC,sBAAgC,oBAAA,iBAAA,WAAA,iBAChC,wBAAgC,oBAAA,mBAAA,WAAA,mBAChC,uBAAgC,oBAAA,kBAAA,WAAA,mBCtC5B,KAAgC,OAAA,YAChC,MPsiER,MOpiEU,WAAA,YAEF,MPuiER,MOriEU,aAAA,YAEF,MPwiER,MOtiEU,cAAA,YAEF,MPyiER,MOviEU,YAAA,YAfF,KAAgC,OAAA,iBAChC,MP8jER,MO5jEU,WAAA,iBAEF,MP+jER,MO7jEU,aAAA,iBAEF,MPgkER,MO9jEU,cAAA,iBAEF,MPikER,MO/jEU,YAAA,iBAfF,KAAgC,OAAA,gBAChC,MPslER,MOplEU,WAAA,gBAEF,MPulER,MOrlEU,aAAA,gBAEF,MPwlER,MOtlEU,cAAA,gBAEF,MPylER,MOvlEU,YAAA,gBAfF,KAAgC,OAAA,eAChC,MP8mER,MO5mEU,WAAA,eAEF,MP+mER,MO7mEU,aAAA,eAEF,MPgnER,MO9mEU,cAAA,eAEF,MPinER,MO/mEU,YAAA,eAfF,KAAgC,OAAA,iBAChC,MPsoER,MOpoEU,WAAA,iBAEF,MPuoER,MOroEU,aAAA,iBAEF,MPwoER,MOtoEU,cAAA,iBAEF,MPyoER,MOvoEU,YAAA,iBAfF,KAAgC,OAAA,eAChC,MP8pER,MO5pEU,WAAA,eAEF,MP+pER,MO7pEU,aAAA,eAEF,MPgqER,MO9pEU,cAAA,eAEF,MPiqER,MO/pEU,YAAA,eAfF,KAAgC,QAAA,YAChC,MPsrER,MOprEU,YAAA,YAEF,MPurER,MOrrEU,cAAA,YAEF,MPwrER,MOtrEU,eAAA,YAEF,MPyrER,MOvrEU,aAAA,YAfF,KAAgC,QAAA,iBAChC,MP8sER,MO5sEU,YAAA,iBAEF,MP+sER,MO7sEU,cAAA,iBAEF,MPgtER,MO9sEU,eAAA,iBAEF,MPitER,MO/sEU,aAAA,iBAfF,KAAgC,QAAA,gBAChC,MPsuER,MOpuEU,YAAA,gBAEF,MPuuER,MOruEU,cAAA,gBAEF,MPwuER,MOtuEU,eAAA,gBAEF,MPyuER,MOvuEU,aAAA,gBAfF,KAAgC,QAAA,eAChC,MP8vER,MO5vEU,YAAA,eAEF,MP+vER,MO7vEU,cAAA,eAEF,MPgwER,MO9vEU,eAAA,eAEF,MPiwER,MO/vEU,aAAA,eAfF,KAAgC,QAAA,iBAChC,MPsxER,MOpxEU,YAAA,iBAEF,MPuxER,MOrxEU,cAAA,iBAEF,MPwxER,MOtxEU,eAAA,iBAEF,MPyxER,MOvxEU,aAAA,iBAfF,KAAgC,QAAA,eAChC,MP8yER,MO5yEU,YAAA,eAEF,MP+yER,MO7yEU,cAAA,eAEF,MPgzER,MO9yEU,eAAA,eAEF,MPizER,MO/yEU,aAAA,eAQF,MAAwB,OAAA,kBACxB,OP+yER,OO7yEU,WAAA,kBAEF,OPgzER,OO9yEU,aAAA,kBAEF,OPizER,OO/yEU,cAAA,kBAEF,OPkzER,OOhzEU,YAAA,kBAfF,MAAwB,OAAA,iBACxB,OPu0ER,OOr0EU,WAAA,iBAEF,OPw0ER,OOt0EU,aAAA,iBAEF,OPy0ER,OOv0EU,cAAA,iBAEF,OP00ER,OOx0EU,YAAA,iBAfF,MAAwB,OAAA,gBACxB,OP+1ER,OO71EU,WAAA,gBAEF,OPg2ER,OO91EU,aAAA,gBAEF,OPi2ER,OO/1EU,cAAA,gBAEF,OPk2ER,OOh2EU,YAAA,gBAfF,MAAwB,OAAA,kBACxB,OPu3ER,OOr3EU,WAAA,kBAEF,OPw3ER,OOt3EU,aAAA,kBAEF,OPy3ER,OOv3EU,cAAA,kBAEF,OP03ER,OOx3EU,YAAA,kBAfF,MAAwB,OAAA,gBACxB,OP+4ER,OO74EU,WAAA,gBAEF,OPg5ER,OO94EU,aAAA,gBAEF,OPi5ER,OO/4EU,cAAA,gBAEF,OPk5ER,OOh5EU,YAAA,gBAMN,QAAmB,OAAA,eACnB,SPk5EJ,SOh5EM,WAAA,eAEF,SPm5EJ,SOj5EM,aAAA,eAEF,SPo5EJ,SOl5EM,cAAA,eAEF,SPq5EJ,SOn5EM,YAAA,eJTF,yBIlDI,QAAgC,OAAA,YAChC,SPs9EN,SOp9EQ,WAAA,YAEF,SPs9EN,SOp9EQ,aAAA,YAEF,SPs9EN,SOp9EQ,cAAA,YAEF,SPs9EN,SOp9EQ,YAAA,YAfF,QAAgC,OAAA,iBAChC,SPy+EN,SOv+EQ,WAAA,iBAEF,SPy+EN,SOv+EQ,aAAA,iBAEF,SPy+EN,SOv+EQ,cAAA,iBAEF,SPy+EN,SOv+EQ,YAAA,iBAfF,QAAgC,OAAA,gBAChC,SP4/EN,SO1/EQ,WAAA,gBAEF,SP4/EN,SO1/EQ,aAAA,gBAEF,SP4/EN,SO1/EQ,cAAA,gBAEF,SP4/EN,SO1/EQ,YAAA,gBAfF,QAAgC,OAAA,eAChC,SP+gFN,SO7gFQ,WAAA,eAEF,SP+gFN,SO7gFQ,aAAA,eAEF,SP+gFN,SO7gFQ,cAAA,eAEF,SP+gFN,SO7gFQ,YAAA,eAfF,QAAgC,OAAA,iBAChC,SPkiFN,SOhiFQ,WAAA,iBAEF,SPkiFN,SOhiFQ,aAAA,iBAEF,SPkiFN,SOhiFQ,cAAA,iBAEF,SPkiFN,SOhiFQ,YAAA,iBAfF,QAAgC,OAAA,eAChC,SPqjFN,SOnjFQ,WAAA,eAEF,SPqjFN,SOnjFQ,aAAA,eAEF,SPqjFN,SOnjFQ,cAAA,eAEF,SPqjFN,SOnjFQ,YAAA,eAfF,QAAgC,QAAA,YAChC,SPwkFN,SOtkFQ,YAAA,YAEF,SPwkFN,SOtkFQ,cAAA,YAEF,SPwkFN,SOtkFQ,eAAA,YAEF,SPwkFN,SOtkFQ,aAAA,YAfF,QAAgC,QAAA,iBAChC,SP2lFN,SOzlFQ,YAAA,iBAEF,SP2lFN,SOzlFQ,cAAA,iBAEF,SP2lFN,SOzlFQ,eAAA,iBAEF,SP2lFN,SOzlFQ,aAAA,iBAfF,QAAgC,QAAA,gBAChC,SP8mFN,SO5mFQ,YAAA,gBAEF,SP8mFN,SO5mFQ,cAAA,gBAEF,SP8mFN,SO5mFQ,eAAA,gBAEF,SP8mFN,SO5mFQ,aAAA,gBAfF,QAAgC,QAAA,eAChC,SPioFN,SO/nFQ,YAAA,eAEF,SPioFN,SO/nFQ,cAAA,eAEF,SPioFN,SO/nFQ,eAAA,eAEF,SPioFN,SO/nFQ,aAAA,eAfF,QAAgC,QAAA,iBAChC,SPopFN,SOlpFQ,YAAA,iBAEF,SPopFN,SOlpFQ,cAAA,iBAEF,SPopFN,SOlpFQ,eAAA,iBAEF,SPopFN,SOlpFQ,aAAA,iBAfF,QAAgC,QAAA,eAChC,SPuqFN,SOrqFQ,YAAA,eAEF,SPuqFN,SOrqFQ,cAAA,eAEF,SPuqFN,SOrqFQ,eAAA,eAEF,SPuqFN,SOrqFQ,aAAA,eAQF,SAAwB,OAAA,kBACxB,UPmqFN,UOjqFQ,WAAA,kBAEF,UPmqFN,UOjqFQ,aAAA,kBAEF,UPmqFN,UOjqFQ,cAAA,kBAEF,UPmqFN,UOjqFQ,YAAA,kBAfF,SAAwB,OAAA,iBACxB,UPsrFN,UOprFQ,WAAA,iBAEF,UPsrFN,UOprFQ,aAAA,iBAEF,UPsrFN,UOprFQ,cAAA,iBAEF,UPsrFN,UOprFQ,YAAA,iBAfF,SAAwB,OAAA,gBACxB,UPysFN,UOvsFQ,WAAA,gBAEF,UPysFN,UOvsFQ,aAAA,gBAEF,UPysFN,UOvsFQ,cAAA,gBAEF,UPysFN,UOvsFQ,YAAA,gBAfF,SAAwB,OAAA,kBACxB,UP4tFN,UO1tFQ,WAAA,kBAEF,UP4tFN,UO1tFQ,aAAA,kBAEF,UP4tFN,UO1tFQ,cAAA,kBAEF,UP4tFN,UO1tFQ,YAAA,kBAfF,SAAwB,OAAA,gBACxB,UP+uFN,UO7uFQ,WAAA,gBAEF,UP+uFN,UO7uFQ,aAAA,gBAEF,UP+uFN,UO7uFQ,cAAA,gBAEF,UP+uFN,UO7uFQ,YAAA,gBAMN,WAAmB,OAAA,eACnB,YP6uFF,YO3uFI,WAAA,eAEF,YP6uFF,YO3uFI,aAAA,eAEF,YP6uFF,YO3uFI,cAAA,eAEF,YP6uFF,YO3uFI,YAAA,gBJTF,yBIlDI,QAAgC,OAAA,YAChC,SP+yFN,SO7yFQ,WAAA,YAEF,SP+yFN,SO7yFQ,aAAA,YAEF,SP+yFN,SO7yFQ,cAAA,YAEF,SP+yFN,SO7yFQ,YAAA,YAfF,QAAgC,OAAA,iBAChC,SPk0FN,SOh0FQ,WAAA,iBAEF,SPk0FN,SOh0FQ,aAAA,iBAEF,SPk0FN,SOh0FQ,cAAA,iBAEF,SPk0FN,SOh0FQ,YAAA,iBAfF,QAAgC,OAAA,gBAChC,SPq1FN,SOn1FQ,WAAA,gBAEF,SPq1FN,SOn1FQ,aAAA,gBAEF,SPq1FN,SOn1FQ,cAAA,gBAEF,SPq1FN,SOn1FQ,YAAA,gBAfF,QAAgC,OAAA,eAChC,SPw2FN,SOt2FQ,WAAA,eAEF,SPw2FN,SOt2FQ,aAAA,eAEF,SPw2FN,SOt2FQ,cAAA,eAEF,SPw2FN,SOt2FQ,YAAA,eAfF,QAAgC,OAAA,iBAChC,SP23FN,SOz3FQ,WAAA,iBAEF,SP23FN,SOz3FQ,aAAA,iBAEF,SP23FN,SOz3FQ,cAAA,iBAEF,SP23FN,SOz3FQ,YAAA,iBAfF,QAAgC,OAAA,eAChC,SP84FN,SO54FQ,WAAA,eAEF,SP84FN,SO54FQ,aAAA,eAEF,SP84FN,SO54FQ,cAAA,eAEF,SP84FN,SO54FQ,YAAA,eAfF,QAAgC,QAAA,YAChC,SPi6FN,SO/5FQ,YAAA,YAEF,SPi6FN,SO/5FQ,cAAA,YAEF,SPi6FN,SO/5FQ,eAAA,YAEF,SPi6FN,SO/5FQ,aAAA,YAfF,QAAgC,QAAA,iBAChC,SPo7FN,SOl7FQ,YAAA,iBAEF,SPo7FN,SOl7FQ,cAAA,iBAEF,SPo7FN,SOl7FQ,eAAA,iBAEF,SPo7FN,SOl7FQ,aAAA,iBAfF,QAAgC,QAAA,gBAChC,SPu8FN,SOr8FQ,YAAA,gBAEF,SPu8FN,SOr8FQ,cAAA,gBAEF,SPu8FN,SOr8FQ,eAAA,gBAEF,SPu8FN,SOr8FQ,aAAA,gBAfF,QAAgC,QAAA,eAChC,SP09FN,SOx9FQ,YAAA,eAEF,SP09FN,SOx9FQ,cAAA,eAEF,SP09FN,SOx9FQ,eAAA,eAEF,SP09FN,SOx9FQ,aAAA,eAfF,QAAgC,QAAA,iBAChC,SP6+FN,SO3+FQ,YAAA,iBAEF,SP6+FN,SO3+FQ,cAAA,iBAEF,SP6+FN,SO3+FQ,eAAA,iBAEF,SP6+FN,SO3+FQ,aAAA,iBAfF,QAAgC,QAAA,eAChC,SPggGN,SO9/FQ,YAAA,eAEF,SPggGN,SO9/FQ,cAAA,eAEF,SPggGN,SO9/FQ,eAAA,eAEF,SPggGN,SO9/FQ,aAAA,eAQF,SAAwB,OAAA,kBACxB,UP4/FN,UO1/FQ,WAAA,kBAEF,UP4/FN,UO1/FQ,aAAA,kBAEF,UP4/FN,UO1/FQ,cAAA,kBAEF,UP4/FN,UO1/FQ,YAAA,kBAfF,SAAwB,OAAA,iBACxB,UP+gGN,UO7gGQ,WAAA,iBAEF,UP+gGN,UO7gGQ,aAAA,iBAEF,UP+gGN,UO7gGQ,cAAA,iBAEF,UP+gGN,UO7gGQ,YAAA,iBAfF,SAAwB,OAAA,gBACxB,UPkiGN,UOhiGQ,WAAA,gBAEF,UPkiGN,UOhiGQ,aAAA,gBAEF,UPkiGN,UOhiGQ,cAAA,gBAEF,UPkiGN,UOhiGQ,YAAA,gBAfF,SAAwB,OAAA,kBACxB,UPqjGN,UOnjGQ,WAAA,kBAEF,UPqjGN,UOnjGQ,aAAA,kBAEF,UPqjGN,UOnjGQ,cAAA,kBAEF,UPqjGN,UOnjGQ,YAAA,kBAfF,SAAwB,OAAA,gBACxB,UPwkGN,UOtkGQ,WAAA,gBAEF,UPwkGN,UOtkGQ,aAAA,gBAEF,UPwkGN,UOtkGQ,cAAA,gBAEF,UPwkGN,UOtkGQ,YAAA,gBAMN,WAAmB,OAAA,eACnB,YPskGF,YOpkGI,WAAA,eAEF,YPskGF,YOpkGI,aAAA,eAEF,YPskGF,YOpkGI,cAAA,eAEF,YPskGF,YOpkGI,YAAA,gBJTF,yBIlDI,QAAgC,OAAA,YAChC,SPwoGN,SOtoGQ,WAAA,YAEF,SPwoGN,SOtoGQ,aAAA,YAEF,SPwoGN,SOtoGQ,cAAA,YAEF,SPwoGN,SOtoGQ,YAAA,YAfF,QAAgC,OAAA,iBAChC,SP2pGN,SOzpGQ,WAAA,iBAEF,SP2pGN,SOzpGQ,aAAA,iBAEF,SP2pGN,SOzpGQ,cAAA,iBAEF,SP2pGN,SOzpGQ,YAAA,iBAfF,QAAgC,OAAA,gBAChC,SP8qGN,SO5qGQ,WAAA,gBAEF,SP8qGN,SO5qGQ,aAAA,gBAEF,SP8qGN,SO5qGQ,cAAA,gBAEF,SP8qGN,SO5qGQ,YAAA,gBAfF,QAAgC,OAAA,eAChC,SPisGN,SO/rGQ,WAAA,eAEF,SPisGN,SO/rGQ,aAAA,eAEF,SPisGN,SO/rGQ,cAAA,eAEF,SPisGN,SO/rGQ,YAAA,eAfF,QAAgC,OAAA,iBAChC,SPotGN,SOltGQ,WAAA,iBAEF,SPotGN,SOltGQ,aAAA,iBAEF,SPotGN,SOltGQ,cAAA,iBAEF,SPotGN,SOltGQ,YAAA,iBAfF,QAAgC,OAAA,eAChC,SPuuGN,SOruGQ,WAAA,eAEF,SPuuGN,SOruGQ,aAAA,eAEF,SPuuGN,SOruGQ,cAAA,eAEF,SPuuGN,SOruGQ,YAAA,eAfF,QAAgC,QAAA,YAChC,SP0vGN,SOxvGQ,YAAA,YAEF,SP0vGN,SOxvGQ,cAAA,YAEF,SP0vGN,SOxvGQ,eAAA,YAEF,SP0vGN,SOxvGQ,aAAA,YAfF,QAAgC,QAAA,iBAChC,SP6wGN,SO3wGQ,YAAA,iBAEF,SP6wGN,SO3wGQ,cAAA,iBAEF,SP6wGN,SO3wGQ,eAAA,iBAEF,SP6wGN,SO3wGQ,aAAA,iBAfF,QAAgC,QAAA,gBAChC,SPgyGN,SO9xGQ,YAAA,gBAEF,SPgyGN,SO9xGQ,cAAA,gBAEF,SPgyGN,SO9xGQ,eAAA,gBAEF,SPgyGN,SO9xGQ,aAAA,gBAfF,QAAgC,QAAA,eAChC,SPmzGN,SOjzGQ,YAAA,eAEF,SPmzGN,SOjzGQ,cAAA,eAEF,SPmzGN,SOjzGQ,eAAA,eAEF,SPmzGN,SOjzGQ,aAAA,eAfF,QAAgC,QAAA,iBAChC,SPs0GN,SOp0GQ,YAAA,iBAEF,SPs0GN,SOp0GQ,cAAA,iBAEF,SPs0GN,SOp0GQ,eAAA,iBAEF,SPs0GN,SOp0GQ,aAAA,iBAfF,QAAgC,QAAA,eAChC,SPy1GN,SOv1GQ,YAAA,eAEF,SPy1GN,SOv1GQ,cAAA,eAEF,SPy1GN,SOv1GQ,eAAA,eAEF,SPy1GN,SOv1GQ,aAAA,eAQF,SAAwB,OAAA,kBACxB,UPq1GN,UOn1GQ,WAAA,kBAEF,UPq1GN,UOn1GQ,aAAA,kBAEF,UPq1GN,UOn1GQ,cAAA,kBAEF,UPq1GN,UOn1GQ,YAAA,kBAfF,SAAwB,OAAA,iBACxB,UPw2GN,UOt2GQ,WAAA,iBAEF,UPw2GN,UOt2GQ,aAAA,iBAEF,UPw2GN,UOt2GQ,cAAA,iBAEF,UPw2GN,UOt2GQ,YAAA,iBAfF,SAAwB,OAAA,gBACxB,UP23GN,UOz3GQ,WAAA,gBAEF,UP23GN,UOz3GQ,aAAA,gBAEF,UP23GN,UOz3GQ,cAAA,gBAEF,UP23GN,UOz3GQ,YAAA,gBAfF,SAAwB,OAAA,kBACxB,UP84GN,UO54GQ,WAAA,kBAEF,UP84GN,UO54GQ,aAAA,kBAEF,UP84GN,UO54GQ,cAAA,kBAEF,UP84GN,UO54GQ,YAAA,kBAfF,SAAwB,OAAA,gBACxB,UPi6GN,UO/5GQ,WAAA,gBAEF,UPi6GN,UO/5GQ,aAAA,gBAEF,UPi6GN,UO/5GQ,cAAA,gBAEF,UPi6GN,UO/5GQ,YAAA,gBAMN,WAAmB,OAAA,eACnB,YP+5GF,YO75GI,WAAA,eAEF,YP+5GF,YO75GI,aAAA,eAEF,YP+5GF,YO75GI,cAAA,eAEF,YP+5GF,YO75GI,YAAA,gBJTF,0BIlDI,QAAgC,OAAA,YAChC,SPi+GN,SO/9GQ,WAAA,YAEF,SPi+GN,SO/9GQ,aAAA,YAEF,SPi+GN,SO/9GQ,cAAA,YAEF,SPi+GN,SO/9GQ,YAAA,YAfF,QAAgC,OAAA,iBAChC,SPo/GN,SOl/GQ,WAAA,iBAEF,SPo/GN,SOl/GQ,aAAA,iBAEF,SPo/GN,SOl/GQ,cAAA,iBAEF,SPo/GN,SOl/GQ,YAAA,iBAfF,QAAgC,OAAA,gBAChC,SPugHN,SOrgHQ,WAAA,gBAEF,SPugHN,SOrgHQ,aAAA,gBAEF,SPugHN,SOrgHQ,cAAA,gBAEF,SPugHN,SOrgHQ,YAAA,gBAfF,QAAgC,OAAA,eAChC,SP0hHN,SOxhHQ,WAAA,eAEF,SP0hHN,SOxhHQ,aAAA,eAEF,SP0hHN,SOxhHQ,cAAA,eAEF,SP0hHN,SOxhHQ,YAAA,eAfF,QAAgC,OAAA,iBAChC,SP6iHN,SO3iHQ,WAAA,iBAEF,SP6iHN,SO3iHQ,aAAA,iBAEF,SP6iHN,SO3iHQ,cAAA,iBAEF,SP6iHN,SO3iHQ,YAAA,iBAfF,QAAgC,OAAA,eAChC,SPgkHN,SO9jHQ,WAAA,eAEF,SPgkHN,SO9jHQ,aAAA,eAEF,SPgkHN,SO9jHQ,cAAA,eAEF,SPgkHN,SO9jHQ,YAAA,eAfF,QAAgC,QAAA,YAChC,SPmlHN,SOjlHQ,YAAA,YAEF,SPmlHN,SOjlHQ,cAAA,YAEF,SPmlHN,SOjlHQ,eAAA,YAEF,SPmlHN,SOjlHQ,aAAA,YAfF,QAAgC,QAAA,iBAChC,SPsmHN,SOpmHQ,YAAA,iBAEF,SPsmHN,SOpmHQ,cAAA,iBAEF,SPsmHN,SOpmHQ,eAAA,iBAEF,SPsmHN,SOpmHQ,aAAA,iBAfF,QAAgC,QAAA,gBAChC,SPynHN,SOvnHQ,YAAA,gBAEF,SPynHN,SOvnHQ,cAAA,gBAEF,SPynHN,SOvnHQ,eAAA,gBAEF,SPynHN,SOvnHQ,aAAA,gBAfF,QAAgC,QAAA,eAChC,SP4oHN,SO1oHQ,YAAA,eAEF,SP4oHN,SO1oHQ,cAAA,eAEF,SP4oHN,SO1oHQ,eAAA,eAEF,SP4oHN,SO1oHQ,aAAA,eAfF,QAAgC,QAAA,iBAChC,SP+pHN,SO7pHQ,YAAA,iBAEF,SP+pHN,SO7pHQ,cAAA,iBAEF,SP+pHN,SO7pHQ,eAAA,iBAEF,SP+pHN,SO7pHQ,aAAA,iBAfF,QAAgC,QAAA,eAChC,SPkrHN,SOhrHQ,YAAA,eAEF,SPkrHN,SOhrHQ,cAAA,eAEF,SPkrHN,SOhrHQ,eAAA,eAEF,SPkrHN,SOhrHQ,aAAA,eAQF,SAAwB,OAAA,kBACxB,UP8qHN,UO5qHQ,WAAA,kBAEF,UP8qHN,UO5qHQ,aAAA,kBAEF,UP8qHN,UO5qHQ,cAAA,kBAEF,UP8qHN,UO5qHQ,YAAA,kBAfF,SAAwB,OAAA,iBACxB,UPisHN,UO/rHQ,WAAA,iBAEF,UPisHN,UO/rHQ,aAAA,iBAEF,UPisHN,UO/rHQ,cAAA,iBAEF,UPisHN,UO/rHQ,YAAA,iBAfF,SAAwB,OAAA,gBACxB,UPotHN,UOltHQ,WAAA,gBAEF,UPotHN,UOltHQ,aAAA,gBAEF,UPotHN,UOltHQ,cAAA,gBAEF,UPotHN,UOltHQ,YAAA,gBAfF,SAAwB,OAAA,kBACxB,UPuuHN,UOruHQ,WAAA,kBAEF,UPuuHN,UOruHQ,aAAA,kBAEF,UPuuHN,UOruHQ,cAAA,kBAEF,UPuuHN,UOruHQ,YAAA,kBAfF,SAAwB,OAAA,gBACxB,UP0vHN,UOxvHQ,WAAA,gBAEF,UP0vHN,UOxvHQ,aAAA,gBAEF,UP0vHN,UOxvHQ,cAAA,gBAEF,UP0vHN,UOxvHQ,YAAA,gBAMN,WAAmB,OAAA,eACnB,YPwvHF,YOtvHI,WAAA,eAEF,YPwvHF,YOtvHI,aAAA,eAEF,YPwvHF,YOtvHI,cAAA,eAEF,YPwvHF,YOtvHI,YAAA","sourcesContent":["/*!\n * Bootstrap Grid v4.5.0 (https://getbootstrap.com/)\n * Copyright 2011-2020 The Bootstrap Authors\n * Copyright 2011-2020 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\nhtml {\n box-sizing: border-box;\n -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n@import \"functions\";\n@import \"variables\";\n\n@import \"mixins/breakpoints\";\n@import \"mixins/grid-framework\";\n@import \"mixins/grid\";\n\n@import \"grid\";\n@import \"utilities/display\";\n@import \"utilities/flex\";\n@import \"utilities/spacing\";\n","/*!\n * Bootstrap Grid v4.5.0 (https://getbootstrap.com/)\n * Copyright 2011-2020 The Bootstrap Authors\n * Copyright 2011-2020 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\nhtml {\n box-sizing: border-box;\n -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n.container {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n@media (min-width: 576px) {\n .container {\n max-width: 540px;\n }\n}\n\n@media (min-width: 768px) {\n .container {\n max-width: 720px;\n }\n}\n\n@media (min-width: 992px) {\n .container {\n max-width: 960px;\n }\n}\n\n@media (min-width: 1200px) {\n .container {\n max-width: 1140px;\n }\n}\n\n.container-fluid, .container-sm, .container-md, .container-lg, .container-xl {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n@media (min-width: 576px) {\n .container, .container-sm {\n max-width: 540px;\n }\n}\n\n@media (min-width: 768px) {\n .container, .container-sm, .container-md {\n max-width: 720px;\n }\n}\n\n@media (min-width: 992px) {\n .container, .container-sm, .container-md, .container-lg {\n max-width: 960px;\n }\n}\n\n@media (min-width: 1200px) {\n .container, .container-sm, .container-md, .container-lg, .container-xl {\n max-width: 1140px;\n }\n}\n\n.row {\n display: -ms-flexbox;\n display: flex;\n -ms-flex-wrap: wrap;\n flex-wrap: wrap;\n margin-right: -15px;\n margin-left: -15px;\n}\n\n.no-gutters {\n margin-right: 0;\n margin-left: 0;\n}\n\n.no-gutters > .col,\n.no-gutters > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n}\n\n.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col,\n.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,\n.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,\n.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,\n.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,\n.col-xl-auto {\n position: relative;\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n}\n\n.col {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n min-width: 0;\n max-width: 100%;\n}\n\n.row-cols-1 > * {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n}\n\n.row-cols-2 > * {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n}\n\n.row-cols-3 > * {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n}\n\n.row-cols-4 > * {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n}\n\n.row-cols-5 > * {\n -ms-flex: 0 0 20%;\n flex: 0 0 20%;\n max-width: 20%;\n}\n\n.row-cols-6 > * {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n}\n\n.col-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n}\n\n.col-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n}\n\n.col-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n}\n\n.col-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n}\n\n.col-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n}\n\n.col-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n}\n\n.col-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n}\n\n.col-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n}\n\n.col-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n}\n\n.col-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n}\n\n.col-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n}\n\n.col-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n}\n\n.col-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n}\n\n.order-first {\n -ms-flex-order: -1;\n order: -1;\n}\n\n.order-last {\n -ms-flex-order: 13;\n order: 13;\n}\n\n.order-0 {\n -ms-flex-order: 0;\n order: 0;\n}\n\n.order-1 {\n -ms-flex-order: 1;\n order: 1;\n}\n\n.order-2 {\n -ms-flex-order: 2;\n order: 2;\n}\n\n.order-3 {\n -ms-flex-order: 3;\n order: 3;\n}\n\n.order-4 {\n -ms-flex-order: 4;\n order: 4;\n}\n\n.order-5 {\n -ms-flex-order: 5;\n order: 5;\n}\n\n.order-6 {\n -ms-flex-order: 6;\n order: 6;\n}\n\n.order-7 {\n -ms-flex-order: 7;\n order: 7;\n}\n\n.order-8 {\n -ms-flex-order: 8;\n order: 8;\n}\n\n.order-9 {\n -ms-flex-order: 9;\n order: 9;\n}\n\n.order-10 {\n -ms-flex-order: 10;\n order: 10;\n}\n\n.order-11 {\n -ms-flex-order: 11;\n order: 11;\n}\n\n.order-12 {\n -ms-flex-order: 12;\n order: 12;\n}\n\n.offset-1 {\n margin-left: 8.333333%;\n}\n\n.offset-2 {\n margin-left: 16.666667%;\n}\n\n.offset-3 {\n margin-left: 25%;\n}\n\n.offset-4 {\n margin-left: 33.333333%;\n}\n\n.offset-5 {\n margin-left: 41.666667%;\n}\n\n.offset-6 {\n margin-left: 50%;\n}\n\n.offset-7 {\n margin-left: 58.333333%;\n}\n\n.offset-8 {\n margin-left: 66.666667%;\n}\n\n.offset-9 {\n margin-left: 75%;\n}\n\n.offset-10 {\n margin-left: 83.333333%;\n}\n\n.offset-11 {\n margin-left: 91.666667%;\n}\n\n@media (min-width: 576px) {\n .col-sm {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n min-width: 0;\n max-width: 100%;\n }\n .row-cols-sm-1 > * {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .row-cols-sm-2 > * {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .row-cols-sm-3 > * {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .row-cols-sm-4 > * {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .row-cols-sm-5 > * {\n -ms-flex: 0 0 20%;\n flex: 0 0 20%;\n max-width: 20%;\n }\n .row-cols-sm-6 > * {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-sm-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-sm-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-sm-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-sm-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-sm-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-sm-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-sm-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-sm-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-sm-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-sm-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-sm-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-sm-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-sm-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-sm-first {\n -ms-flex-order: -1;\n order: -1;\n }\n .order-sm-last {\n -ms-flex-order: 13;\n order: 13;\n }\n .order-sm-0 {\n -ms-flex-order: 0;\n order: 0;\n }\n .order-sm-1 {\n -ms-flex-order: 1;\n order: 1;\n }\n .order-sm-2 {\n -ms-flex-order: 2;\n order: 2;\n }\n .order-sm-3 {\n -ms-flex-order: 3;\n order: 3;\n }\n .order-sm-4 {\n -ms-flex-order: 4;\n order: 4;\n }\n .order-sm-5 {\n -ms-flex-order: 5;\n order: 5;\n }\n .order-sm-6 {\n -ms-flex-order: 6;\n order: 6;\n }\n .order-sm-7 {\n -ms-flex-order: 7;\n order: 7;\n }\n .order-sm-8 {\n -ms-flex-order: 8;\n order: 8;\n }\n .order-sm-9 {\n -ms-flex-order: 9;\n order: 9;\n }\n .order-sm-10 {\n -ms-flex-order: 10;\n order: 10;\n }\n .order-sm-11 {\n -ms-flex-order: 11;\n order: 11;\n }\n .order-sm-12 {\n -ms-flex-order: 12;\n order: 12;\n }\n .offset-sm-0 {\n margin-left: 0;\n }\n .offset-sm-1 {\n margin-left: 8.333333%;\n }\n .offset-sm-2 {\n margin-left: 16.666667%;\n }\n .offset-sm-3 {\n margin-left: 25%;\n }\n .offset-sm-4 {\n margin-left: 33.333333%;\n }\n .offset-sm-5 {\n margin-left: 41.666667%;\n }\n .offset-sm-6 {\n margin-left: 50%;\n }\n .offset-sm-7 {\n margin-left: 58.333333%;\n }\n .offset-sm-8 {\n margin-left: 66.666667%;\n }\n .offset-sm-9 {\n margin-left: 75%;\n }\n .offset-sm-10 {\n margin-left: 83.333333%;\n }\n .offset-sm-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 768px) {\n .col-md {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n min-width: 0;\n max-width: 100%;\n }\n .row-cols-md-1 > * {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .row-cols-md-2 > * {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .row-cols-md-3 > * {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .row-cols-md-4 > * {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .row-cols-md-5 > * {\n -ms-flex: 0 0 20%;\n flex: 0 0 20%;\n max-width: 20%;\n }\n .row-cols-md-6 > * {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-md-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-md-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-md-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-md-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-md-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-md-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-md-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-md-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-md-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-md-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-md-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-md-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-md-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-md-first {\n -ms-flex-order: -1;\n order: -1;\n }\n .order-md-last {\n -ms-flex-order: 13;\n order: 13;\n }\n .order-md-0 {\n -ms-flex-order: 0;\n order: 0;\n }\n .order-md-1 {\n -ms-flex-order: 1;\n order: 1;\n }\n .order-md-2 {\n -ms-flex-order: 2;\n order: 2;\n }\n .order-md-3 {\n -ms-flex-order: 3;\n order: 3;\n }\n .order-md-4 {\n -ms-flex-order: 4;\n order: 4;\n }\n .order-md-5 {\n -ms-flex-order: 5;\n order: 5;\n }\n .order-md-6 {\n -ms-flex-order: 6;\n order: 6;\n }\n .order-md-7 {\n -ms-flex-order: 7;\n order: 7;\n }\n .order-md-8 {\n -ms-flex-order: 8;\n order: 8;\n }\n .order-md-9 {\n -ms-flex-order: 9;\n order: 9;\n }\n .order-md-10 {\n -ms-flex-order: 10;\n order: 10;\n }\n .order-md-11 {\n -ms-flex-order: 11;\n order: 11;\n }\n .order-md-12 {\n -ms-flex-order: 12;\n order: 12;\n }\n .offset-md-0 {\n margin-left: 0;\n }\n .offset-md-1 {\n margin-left: 8.333333%;\n }\n .offset-md-2 {\n margin-left: 16.666667%;\n }\n .offset-md-3 {\n margin-left: 25%;\n }\n .offset-md-4 {\n margin-left: 33.333333%;\n }\n .offset-md-5 {\n margin-left: 41.666667%;\n }\n .offset-md-6 {\n margin-left: 50%;\n }\n .offset-md-7 {\n margin-left: 58.333333%;\n }\n .offset-md-8 {\n margin-left: 66.666667%;\n }\n .offset-md-9 {\n margin-left: 75%;\n }\n .offset-md-10 {\n margin-left: 83.333333%;\n }\n .offset-md-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 992px) {\n .col-lg {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n min-width: 0;\n max-width: 100%;\n }\n .row-cols-lg-1 > * {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .row-cols-lg-2 > * {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .row-cols-lg-3 > * {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .row-cols-lg-4 > * {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .row-cols-lg-5 > * {\n -ms-flex: 0 0 20%;\n flex: 0 0 20%;\n max-width: 20%;\n }\n .row-cols-lg-6 > * {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-lg-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-lg-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-lg-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-lg-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-lg-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-lg-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-lg-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-lg-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-lg-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-lg-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-lg-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-lg-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-lg-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-lg-first {\n -ms-flex-order: -1;\n order: -1;\n }\n .order-lg-last {\n -ms-flex-order: 13;\n order: 13;\n }\n .order-lg-0 {\n -ms-flex-order: 0;\n order: 0;\n }\n .order-lg-1 {\n -ms-flex-order: 1;\n order: 1;\n }\n .order-lg-2 {\n -ms-flex-order: 2;\n order: 2;\n }\n .order-lg-3 {\n -ms-flex-order: 3;\n order: 3;\n }\n .order-lg-4 {\n -ms-flex-order: 4;\n order: 4;\n }\n .order-lg-5 {\n -ms-flex-order: 5;\n order: 5;\n }\n .order-lg-6 {\n -ms-flex-order: 6;\n order: 6;\n }\n .order-lg-7 {\n -ms-flex-order: 7;\n order: 7;\n }\n .order-lg-8 {\n -ms-flex-order: 8;\n order: 8;\n }\n .order-lg-9 {\n -ms-flex-order: 9;\n order: 9;\n }\n .order-lg-10 {\n -ms-flex-order: 10;\n order: 10;\n }\n .order-lg-11 {\n -ms-flex-order: 11;\n order: 11;\n }\n .order-lg-12 {\n -ms-flex-order: 12;\n order: 12;\n }\n .offset-lg-0 {\n margin-left: 0;\n }\n .offset-lg-1 {\n margin-left: 8.333333%;\n }\n .offset-lg-2 {\n margin-left: 16.666667%;\n }\n .offset-lg-3 {\n margin-left: 25%;\n }\n .offset-lg-4 {\n margin-left: 33.333333%;\n }\n .offset-lg-5 {\n margin-left: 41.666667%;\n }\n .offset-lg-6 {\n margin-left: 50%;\n }\n .offset-lg-7 {\n margin-left: 58.333333%;\n }\n .offset-lg-8 {\n margin-left: 66.666667%;\n }\n .offset-lg-9 {\n margin-left: 75%;\n }\n .offset-lg-10 {\n margin-left: 83.333333%;\n }\n .offset-lg-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 1200px) {\n .col-xl {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n min-width: 0;\n max-width: 100%;\n }\n .row-cols-xl-1 > * {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .row-cols-xl-2 > * {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .row-cols-xl-3 > * {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .row-cols-xl-4 > * {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .row-cols-xl-5 > * {\n -ms-flex: 0 0 20%;\n flex: 0 0 20%;\n max-width: 20%;\n }\n .row-cols-xl-6 > * {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-xl-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: 100%;\n }\n .col-xl-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-xl-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-xl-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-xl-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-xl-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-xl-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-xl-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-xl-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-xl-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-xl-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-xl-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-xl-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-xl-first {\n -ms-flex-order: -1;\n order: -1;\n }\n .order-xl-last {\n -ms-flex-order: 13;\n order: 13;\n }\n .order-xl-0 {\n -ms-flex-order: 0;\n order: 0;\n }\n .order-xl-1 {\n -ms-flex-order: 1;\n order: 1;\n }\n .order-xl-2 {\n -ms-flex-order: 2;\n order: 2;\n }\n .order-xl-3 {\n -ms-flex-order: 3;\n order: 3;\n }\n .order-xl-4 {\n -ms-flex-order: 4;\n order: 4;\n }\n .order-xl-5 {\n -ms-flex-order: 5;\n order: 5;\n }\n .order-xl-6 {\n -ms-flex-order: 6;\n order: 6;\n }\n .order-xl-7 {\n -ms-flex-order: 7;\n order: 7;\n }\n .order-xl-8 {\n -ms-flex-order: 8;\n order: 8;\n }\n .order-xl-9 {\n -ms-flex-order: 9;\n order: 9;\n }\n .order-xl-10 {\n -ms-flex-order: 10;\n order: 10;\n }\n .order-xl-11 {\n -ms-flex-order: 11;\n order: 11;\n }\n .order-xl-12 {\n -ms-flex-order: 12;\n order: 12;\n }\n .offset-xl-0 {\n margin-left: 0;\n }\n .offset-xl-1 {\n margin-left: 8.333333%;\n }\n .offset-xl-2 {\n margin-left: 16.666667%;\n }\n .offset-xl-3 {\n margin-left: 25%;\n }\n .offset-xl-4 {\n margin-left: 33.333333%;\n }\n .offset-xl-5 {\n margin-left: 41.666667%;\n }\n .offset-xl-6 {\n margin-left: 50%;\n }\n .offset-xl-7 {\n margin-left: 58.333333%;\n }\n .offset-xl-8 {\n margin-left: 66.666667%;\n }\n .offset-xl-9 {\n margin-left: 75%;\n }\n .offset-xl-10 {\n margin-left: 83.333333%;\n }\n .offset-xl-11 {\n margin-left: 91.666667%;\n }\n}\n\n.d-none {\n display: none !important;\n}\n\n.d-inline {\n display: inline !important;\n}\n\n.d-inline-block {\n display: inline-block !important;\n}\n\n.d-block {\n display: block !important;\n}\n\n.d-table {\n display: table !important;\n}\n\n.d-table-row {\n display: table-row !important;\n}\n\n.d-table-cell {\n display: table-cell !important;\n}\n\n.d-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n}\n\n.d-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n}\n\n@media (min-width: 576px) {\n .d-sm-none {\n display: none !important;\n }\n .d-sm-inline {\n display: inline !important;\n }\n .d-sm-inline-block {\n display: inline-block !important;\n }\n .d-sm-block {\n display: block !important;\n }\n .d-sm-table {\n display: table !important;\n }\n .d-sm-table-row {\n display: table-row !important;\n }\n .d-sm-table-cell {\n display: table-cell !important;\n }\n .d-sm-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-sm-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 768px) {\n .d-md-none {\n display: none !important;\n }\n .d-md-inline {\n display: inline !important;\n }\n .d-md-inline-block {\n display: inline-block !important;\n }\n .d-md-block {\n display: block !important;\n }\n .d-md-table {\n display: table !important;\n }\n .d-md-table-row {\n display: table-row !important;\n }\n .d-md-table-cell {\n display: table-cell !important;\n }\n .d-md-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-md-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 992px) {\n .d-lg-none {\n display: none !important;\n }\n .d-lg-inline {\n display: inline !important;\n }\n .d-lg-inline-block {\n display: inline-block !important;\n }\n .d-lg-block {\n display: block !important;\n }\n .d-lg-table {\n display: table !important;\n }\n .d-lg-table-row {\n display: table-row !important;\n }\n .d-lg-table-cell {\n display: table-cell !important;\n }\n .d-lg-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-lg-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 1200px) {\n .d-xl-none {\n display: none !important;\n }\n .d-xl-inline {\n display: inline !important;\n }\n .d-xl-inline-block {\n display: inline-block !important;\n }\n .d-xl-block {\n display: block !important;\n }\n .d-xl-table {\n display: table !important;\n }\n .d-xl-table-row {\n display: table-row !important;\n }\n .d-xl-table-cell {\n display: table-cell !important;\n }\n .d-xl-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-xl-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n@media print {\n .d-print-none {\n display: none !important;\n }\n .d-print-inline {\n display: inline !important;\n }\n .d-print-inline-block {\n display: inline-block !important;\n }\n .d-print-block {\n display: block !important;\n }\n .d-print-table {\n display: table !important;\n }\n .d-print-table-row {\n display: table-row !important;\n }\n .d-print-table-cell {\n display: table-cell !important;\n }\n .d-print-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-print-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n.flex-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n}\n\n.flex-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n}\n\n.flex-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n}\n\n.flex-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n}\n\n.flex-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n}\n\n.flex-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n}\n\n.flex-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n}\n\n.flex-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n}\n\n.flex-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n}\n\n.flex-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n}\n\n.flex-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n}\n\n.flex-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n}\n\n.justify-content-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n}\n\n.justify-content-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n}\n\n.justify-content-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n}\n\n.justify-content-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n}\n\n.justify-content-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n}\n\n.align-items-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n}\n\n.align-items-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n}\n\n.align-items-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n}\n\n.align-items-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n}\n\n.align-items-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n}\n\n.align-content-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n}\n\n.align-content-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n}\n\n.align-content-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n}\n\n.align-content-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n}\n\n.align-content-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n}\n\n.align-content-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n}\n\n.align-self-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n}\n\n.align-self-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n}\n\n.align-self-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n}\n\n.align-self-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n}\n\n.align-self-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n}\n\n.align-self-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n}\n\n@media (min-width: 576px) {\n .flex-sm-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n }\n .flex-sm-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n }\n .flex-sm-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n }\n .flex-sm-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n }\n .flex-sm-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n }\n .flex-sm-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n }\n .flex-sm-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n }\n .flex-sm-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n }\n .flex-sm-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n }\n .flex-sm-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n }\n .flex-sm-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n }\n .flex-sm-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n }\n .justify-content-sm-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n }\n .justify-content-sm-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n }\n .justify-content-sm-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n }\n .justify-content-sm-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n }\n .justify-content-sm-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n }\n .align-items-sm-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n }\n .align-items-sm-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n }\n .align-items-sm-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n }\n .align-items-sm-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n }\n .align-items-sm-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n }\n .align-content-sm-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n }\n .align-content-sm-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n }\n .align-content-sm-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n }\n .align-content-sm-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n }\n .align-content-sm-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n }\n .align-content-sm-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n }\n .align-self-sm-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n }\n .align-self-sm-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n }\n .align-self-sm-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n }\n .align-self-sm-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n }\n .align-self-sm-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n }\n .align-self-sm-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 768px) {\n .flex-md-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n }\n .flex-md-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n }\n .flex-md-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n }\n .flex-md-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n }\n .flex-md-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n }\n .flex-md-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n }\n .flex-md-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n }\n .flex-md-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n }\n .flex-md-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n }\n .flex-md-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n }\n .flex-md-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n }\n .flex-md-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n }\n .justify-content-md-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n }\n .justify-content-md-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n }\n .justify-content-md-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n }\n .justify-content-md-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n }\n .justify-content-md-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n }\n .align-items-md-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n }\n .align-items-md-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n }\n .align-items-md-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n }\n .align-items-md-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n }\n .align-items-md-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n }\n .align-content-md-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n }\n .align-content-md-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n }\n .align-content-md-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n }\n .align-content-md-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n }\n .align-content-md-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n }\n .align-content-md-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n }\n .align-self-md-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n }\n .align-self-md-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n }\n .align-self-md-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n }\n .align-self-md-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n }\n .align-self-md-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n }\n .align-self-md-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 992px) {\n .flex-lg-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n }\n .flex-lg-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n }\n .flex-lg-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n }\n .flex-lg-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n }\n .flex-lg-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n }\n .flex-lg-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n }\n .flex-lg-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n }\n .flex-lg-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n }\n .flex-lg-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n }\n .flex-lg-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n }\n .flex-lg-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n }\n .flex-lg-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n }\n .justify-content-lg-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n }\n .justify-content-lg-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n }\n .justify-content-lg-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n }\n .justify-content-lg-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n }\n .justify-content-lg-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n }\n .align-items-lg-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n }\n .align-items-lg-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n }\n .align-items-lg-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n }\n .align-items-lg-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n }\n .align-items-lg-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n }\n .align-content-lg-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n }\n .align-content-lg-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n }\n .align-content-lg-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n }\n .align-content-lg-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n }\n .align-content-lg-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n }\n .align-content-lg-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n }\n .align-self-lg-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n }\n .align-self-lg-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n }\n .align-self-lg-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n }\n .align-self-lg-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n }\n .align-self-lg-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n }\n .align-self-lg-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 1200px) {\n .flex-xl-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n }\n .flex-xl-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n }\n .flex-xl-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n }\n .flex-xl-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n }\n .flex-xl-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n }\n .flex-xl-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n }\n .flex-xl-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n }\n .flex-xl-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n }\n .flex-xl-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n }\n .flex-xl-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n }\n .flex-xl-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n }\n .flex-xl-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n }\n .justify-content-xl-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n }\n .justify-content-xl-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n }\n .justify-content-xl-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n }\n .justify-content-xl-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n }\n .justify-content-xl-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n }\n .align-items-xl-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n }\n .align-items-xl-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n }\n .align-items-xl-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n }\n .align-items-xl-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n }\n .align-items-xl-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n }\n .align-content-xl-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n }\n .align-content-xl-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n }\n .align-content-xl-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n }\n .align-content-xl-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n }\n .align-content-xl-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n }\n .align-content-xl-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n }\n .align-self-xl-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n }\n .align-self-xl-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n }\n .align-self-xl-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n }\n .align-self-xl-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n }\n .align-self-xl-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n }\n .align-self-xl-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n }\n}\n\n.m-0 {\n margin: 0 !important;\n}\n\n.mt-0,\n.my-0 {\n margin-top: 0 !important;\n}\n\n.mr-0,\n.mx-0 {\n margin-right: 0 !important;\n}\n\n.mb-0,\n.my-0 {\n margin-bottom: 0 !important;\n}\n\n.ml-0,\n.mx-0 {\n margin-left: 0 !important;\n}\n\n.m-1 {\n margin: 0.25rem !important;\n}\n\n.mt-1,\n.my-1 {\n margin-top: 0.25rem !important;\n}\n\n.mr-1,\n.mx-1 {\n margin-right: 0.25rem !important;\n}\n\n.mb-1,\n.my-1 {\n margin-bottom: 0.25rem !important;\n}\n\n.ml-1,\n.mx-1 {\n margin-left: 0.25rem !important;\n}\n\n.m-2 {\n margin: 0.5rem !important;\n}\n\n.mt-2,\n.my-2 {\n margin-top: 0.5rem !important;\n}\n\n.mr-2,\n.mx-2 {\n margin-right: 0.5rem !important;\n}\n\n.mb-2,\n.my-2 {\n margin-bottom: 0.5rem !important;\n}\n\n.ml-2,\n.mx-2 {\n margin-left: 0.5rem !important;\n}\n\n.m-3 {\n margin: 1rem !important;\n}\n\n.mt-3,\n.my-3 {\n margin-top: 1rem !important;\n}\n\n.mr-3,\n.mx-3 {\n margin-right: 1rem !important;\n}\n\n.mb-3,\n.my-3 {\n margin-bottom: 1rem !important;\n}\n\n.ml-3,\n.mx-3 {\n margin-left: 1rem !important;\n}\n\n.m-4 {\n margin: 1.5rem !important;\n}\n\n.mt-4,\n.my-4 {\n margin-top: 1.5rem !important;\n}\n\n.mr-4,\n.mx-4 {\n margin-right: 1.5rem !important;\n}\n\n.mb-4,\n.my-4 {\n margin-bottom: 1.5rem !important;\n}\n\n.ml-4,\n.mx-4 {\n margin-left: 1.5rem !important;\n}\n\n.m-5 {\n margin: 3rem !important;\n}\n\n.mt-5,\n.my-5 {\n margin-top: 3rem !important;\n}\n\n.mr-5,\n.mx-5 {\n margin-right: 3rem !important;\n}\n\n.mb-5,\n.my-5 {\n margin-bottom: 3rem !important;\n}\n\n.ml-5,\n.mx-5 {\n margin-left: 3rem !important;\n}\n\n.p-0 {\n padding: 0 !important;\n}\n\n.pt-0,\n.py-0 {\n padding-top: 0 !important;\n}\n\n.pr-0,\n.px-0 {\n padding-right: 0 !important;\n}\n\n.pb-0,\n.py-0 {\n padding-bottom: 0 !important;\n}\n\n.pl-0,\n.px-0 {\n padding-left: 0 !important;\n}\n\n.p-1 {\n padding: 0.25rem !important;\n}\n\n.pt-1,\n.py-1 {\n padding-top: 0.25rem !important;\n}\n\n.pr-1,\n.px-1 {\n padding-right: 0.25rem !important;\n}\n\n.pb-1,\n.py-1 {\n padding-bottom: 0.25rem !important;\n}\n\n.pl-1,\n.px-1 {\n padding-left: 0.25rem !important;\n}\n\n.p-2 {\n padding: 0.5rem !important;\n}\n\n.pt-2,\n.py-2 {\n padding-top: 0.5rem !important;\n}\n\n.pr-2,\n.px-2 {\n padding-right: 0.5rem !important;\n}\n\n.pb-2,\n.py-2 {\n padding-bottom: 0.5rem !important;\n}\n\n.pl-2,\n.px-2 {\n padding-left: 0.5rem !important;\n}\n\n.p-3 {\n padding: 1rem !important;\n}\n\n.pt-3,\n.py-3 {\n padding-top: 1rem !important;\n}\n\n.pr-3,\n.px-3 {\n padding-right: 1rem !important;\n}\n\n.pb-3,\n.py-3 {\n padding-bottom: 1rem !important;\n}\n\n.pl-3,\n.px-3 {\n padding-left: 1rem !important;\n}\n\n.p-4 {\n padding: 1.5rem !important;\n}\n\n.pt-4,\n.py-4 {\n padding-top: 1.5rem !important;\n}\n\n.pr-4,\n.px-4 {\n padding-right: 1.5rem !important;\n}\n\n.pb-4,\n.py-4 {\n padding-bottom: 1.5rem !important;\n}\n\n.pl-4,\n.px-4 {\n padding-left: 1.5rem !important;\n}\n\n.p-5 {\n padding: 3rem !important;\n}\n\n.pt-5,\n.py-5 {\n padding-top: 3rem !important;\n}\n\n.pr-5,\n.px-5 {\n padding-right: 3rem !important;\n}\n\n.pb-5,\n.py-5 {\n padding-bottom: 3rem !important;\n}\n\n.pl-5,\n.px-5 {\n padding-left: 3rem !important;\n}\n\n.m-n1 {\n margin: -0.25rem !important;\n}\n\n.mt-n1,\n.my-n1 {\n margin-top: -0.25rem !important;\n}\n\n.mr-n1,\n.mx-n1 {\n margin-right: -0.25rem !important;\n}\n\n.mb-n1,\n.my-n1 {\n margin-bottom: -0.25rem !important;\n}\n\n.ml-n1,\n.mx-n1 {\n margin-left: -0.25rem !important;\n}\n\n.m-n2 {\n margin: -0.5rem !important;\n}\n\n.mt-n2,\n.my-n2 {\n margin-top: -0.5rem !important;\n}\n\n.mr-n2,\n.mx-n2 {\n margin-right: -0.5rem !important;\n}\n\n.mb-n2,\n.my-n2 {\n margin-bottom: -0.5rem !important;\n}\n\n.ml-n2,\n.mx-n2 {\n margin-left: -0.5rem !important;\n}\n\n.m-n3 {\n margin: -1rem !important;\n}\n\n.mt-n3,\n.my-n3 {\n margin-top: -1rem !important;\n}\n\n.mr-n3,\n.mx-n3 {\n margin-right: -1rem !important;\n}\n\n.mb-n3,\n.my-n3 {\n margin-bottom: -1rem !important;\n}\n\n.ml-n3,\n.mx-n3 {\n margin-left: -1rem !important;\n}\n\n.m-n4 {\n margin: -1.5rem !important;\n}\n\n.mt-n4,\n.my-n4 {\n margin-top: -1.5rem !important;\n}\n\n.mr-n4,\n.mx-n4 {\n margin-right: -1.5rem !important;\n}\n\n.mb-n4,\n.my-n4 {\n margin-bottom: -1.5rem !important;\n}\n\n.ml-n4,\n.mx-n4 {\n margin-left: -1.5rem !important;\n}\n\n.m-n5 {\n margin: -3rem !important;\n}\n\n.mt-n5,\n.my-n5 {\n margin-top: -3rem !important;\n}\n\n.mr-n5,\n.mx-n5 {\n margin-right: -3rem !important;\n}\n\n.mb-n5,\n.my-n5 {\n margin-bottom: -3rem !important;\n}\n\n.ml-n5,\n.mx-n5 {\n margin-left: -3rem !important;\n}\n\n.m-auto {\n margin: auto !important;\n}\n\n.mt-auto,\n.my-auto {\n margin-top: auto !important;\n}\n\n.mr-auto,\n.mx-auto {\n margin-right: auto !important;\n}\n\n.mb-auto,\n.my-auto {\n margin-bottom: auto !important;\n}\n\n.ml-auto,\n.mx-auto {\n margin-left: auto !important;\n}\n\n@media (min-width: 576px) {\n .m-sm-0 {\n margin: 0 !important;\n }\n .mt-sm-0,\n .my-sm-0 {\n margin-top: 0 !important;\n }\n .mr-sm-0,\n .mx-sm-0 {\n margin-right: 0 !important;\n }\n .mb-sm-0,\n .my-sm-0 {\n margin-bottom: 0 !important;\n }\n .ml-sm-0,\n .mx-sm-0 {\n margin-left: 0 !important;\n }\n .m-sm-1 {\n margin: 0.25rem !important;\n }\n .mt-sm-1,\n .my-sm-1 {\n margin-top: 0.25rem !important;\n }\n .mr-sm-1,\n .mx-sm-1 {\n margin-right: 0.25rem !important;\n }\n .mb-sm-1,\n .my-sm-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-sm-1,\n .mx-sm-1 {\n margin-left: 0.25rem !important;\n }\n .m-sm-2 {\n margin: 0.5rem !important;\n }\n .mt-sm-2,\n .my-sm-2 {\n margin-top: 0.5rem !important;\n }\n .mr-sm-2,\n .mx-sm-2 {\n margin-right: 0.5rem !important;\n }\n .mb-sm-2,\n .my-sm-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-sm-2,\n .mx-sm-2 {\n margin-left: 0.5rem !important;\n }\n .m-sm-3 {\n margin: 1rem !important;\n }\n .mt-sm-3,\n .my-sm-3 {\n margin-top: 1rem !important;\n }\n .mr-sm-3,\n .mx-sm-3 {\n margin-right: 1rem !important;\n }\n .mb-sm-3,\n .my-sm-3 {\n margin-bottom: 1rem !important;\n }\n .ml-sm-3,\n .mx-sm-3 {\n margin-left: 1rem !important;\n }\n .m-sm-4 {\n margin: 1.5rem !important;\n }\n .mt-sm-4,\n .my-sm-4 {\n margin-top: 1.5rem !important;\n }\n .mr-sm-4,\n .mx-sm-4 {\n margin-right: 1.5rem !important;\n }\n .mb-sm-4,\n .my-sm-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-sm-4,\n .mx-sm-4 {\n margin-left: 1.5rem !important;\n }\n .m-sm-5 {\n margin: 3rem !important;\n }\n .mt-sm-5,\n .my-sm-5 {\n margin-top: 3rem !important;\n }\n .mr-sm-5,\n .mx-sm-5 {\n margin-right: 3rem !important;\n }\n .mb-sm-5,\n .my-sm-5 {\n margin-bottom: 3rem !important;\n }\n .ml-sm-5,\n .mx-sm-5 {\n margin-left: 3rem !important;\n }\n .p-sm-0 {\n padding: 0 !important;\n }\n .pt-sm-0,\n .py-sm-0 {\n padding-top: 0 !important;\n }\n .pr-sm-0,\n .px-sm-0 {\n padding-right: 0 !important;\n }\n .pb-sm-0,\n .py-sm-0 {\n padding-bottom: 0 !important;\n }\n .pl-sm-0,\n .px-sm-0 {\n padding-left: 0 !important;\n }\n .p-sm-1 {\n padding: 0.25rem !important;\n }\n .pt-sm-1,\n .py-sm-1 {\n padding-top: 0.25rem !important;\n }\n .pr-sm-1,\n .px-sm-1 {\n padding-right: 0.25rem !important;\n }\n .pb-sm-1,\n .py-sm-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-sm-1,\n .px-sm-1 {\n padding-left: 0.25rem !important;\n }\n .p-sm-2 {\n padding: 0.5rem !important;\n }\n .pt-sm-2,\n .py-sm-2 {\n padding-top: 0.5rem !important;\n }\n .pr-sm-2,\n .px-sm-2 {\n padding-right: 0.5rem !important;\n }\n .pb-sm-2,\n .py-sm-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-sm-2,\n .px-sm-2 {\n padding-left: 0.5rem !important;\n }\n .p-sm-3 {\n padding: 1rem !important;\n }\n .pt-sm-3,\n .py-sm-3 {\n padding-top: 1rem !important;\n }\n .pr-sm-3,\n .px-sm-3 {\n padding-right: 1rem !important;\n }\n .pb-sm-3,\n .py-sm-3 {\n padding-bottom: 1rem !important;\n }\n .pl-sm-3,\n .px-sm-3 {\n padding-left: 1rem !important;\n }\n .p-sm-4 {\n padding: 1.5rem !important;\n }\n .pt-sm-4,\n .py-sm-4 {\n padding-top: 1.5rem !important;\n }\n .pr-sm-4,\n .px-sm-4 {\n padding-right: 1.5rem !important;\n }\n .pb-sm-4,\n .py-sm-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-sm-4,\n .px-sm-4 {\n padding-left: 1.5rem !important;\n }\n .p-sm-5 {\n padding: 3rem !important;\n }\n .pt-sm-5,\n .py-sm-5 {\n padding-top: 3rem !important;\n }\n .pr-sm-5,\n .px-sm-5 {\n padding-right: 3rem !important;\n }\n .pb-sm-5,\n .py-sm-5 {\n padding-bottom: 3rem !important;\n }\n .pl-sm-5,\n .px-sm-5 {\n padding-left: 3rem !important;\n }\n .m-sm-n1 {\n margin: -0.25rem !important;\n }\n .mt-sm-n1,\n .my-sm-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-sm-n1,\n .mx-sm-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-sm-n1,\n .my-sm-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-sm-n1,\n .mx-sm-n1 {\n margin-left: -0.25rem !important;\n }\n .m-sm-n2 {\n margin: -0.5rem !important;\n }\n .mt-sm-n2,\n .my-sm-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-sm-n2,\n .mx-sm-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-sm-n2,\n .my-sm-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-sm-n2,\n .mx-sm-n2 {\n margin-left: -0.5rem !important;\n }\n .m-sm-n3 {\n margin: -1rem !important;\n }\n .mt-sm-n3,\n .my-sm-n3 {\n margin-top: -1rem !important;\n }\n .mr-sm-n3,\n .mx-sm-n3 {\n margin-right: -1rem !important;\n }\n .mb-sm-n3,\n .my-sm-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-sm-n3,\n .mx-sm-n3 {\n margin-left: -1rem !important;\n }\n .m-sm-n4 {\n margin: -1.5rem !important;\n }\n .mt-sm-n4,\n .my-sm-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-sm-n4,\n .mx-sm-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-sm-n4,\n .my-sm-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-sm-n4,\n .mx-sm-n4 {\n margin-left: -1.5rem !important;\n }\n .m-sm-n5 {\n margin: -3rem !important;\n }\n .mt-sm-n5,\n .my-sm-n5 {\n margin-top: -3rem !important;\n }\n .mr-sm-n5,\n .mx-sm-n5 {\n margin-right: -3rem !important;\n }\n .mb-sm-n5,\n .my-sm-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-sm-n5,\n .mx-sm-n5 {\n margin-left: -3rem !important;\n }\n .m-sm-auto {\n margin: auto !important;\n }\n .mt-sm-auto,\n .my-sm-auto {\n margin-top: auto !important;\n }\n .mr-sm-auto,\n .mx-sm-auto {\n margin-right: auto !important;\n }\n .mb-sm-auto,\n .my-sm-auto {\n margin-bottom: auto !important;\n }\n .ml-sm-auto,\n .mx-sm-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 768px) {\n .m-md-0 {\n margin: 0 !important;\n }\n .mt-md-0,\n .my-md-0 {\n margin-top: 0 !important;\n }\n .mr-md-0,\n .mx-md-0 {\n margin-right: 0 !important;\n }\n .mb-md-0,\n .my-md-0 {\n margin-bottom: 0 !important;\n }\n .ml-md-0,\n .mx-md-0 {\n margin-left: 0 !important;\n }\n .m-md-1 {\n margin: 0.25rem !important;\n }\n .mt-md-1,\n .my-md-1 {\n margin-top: 0.25rem !important;\n }\n .mr-md-1,\n .mx-md-1 {\n margin-right: 0.25rem !important;\n }\n .mb-md-1,\n .my-md-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-md-1,\n .mx-md-1 {\n margin-left: 0.25rem !important;\n }\n .m-md-2 {\n margin: 0.5rem !important;\n }\n .mt-md-2,\n .my-md-2 {\n margin-top: 0.5rem !important;\n }\n .mr-md-2,\n .mx-md-2 {\n margin-right: 0.5rem !important;\n }\n .mb-md-2,\n .my-md-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-md-2,\n .mx-md-2 {\n margin-left: 0.5rem !important;\n }\n .m-md-3 {\n margin: 1rem !important;\n }\n .mt-md-3,\n .my-md-3 {\n margin-top: 1rem !important;\n }\n .mr-md-3,\n .mx-md-3 {\n margin-right: 1rem !important;\n }\n .mb-md-3,\n .my-md-3 {\n margin-bottom: 1rem !important;\n }\n .ml-md-3,\n .mx-md-3 {\n margin-left: 1rem !important;\n }\n .m-md-4 {\n margin: 1.5rem !important;\n }\n .mt-md-4,\n .my-md-4 {\n margin-top: 1.5rem !important;\n }\n .mr-md-4,\n .mx-md-4 {\n margin-right: 1.5rem !important;\n }\n .mb-md-4,\n .my-md-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-md-4,\n .mx-md-4 {\n margin-left: 1.5rem !important;\n }\n .m-md-5 {\n margin: 3rem !important;\n }\n .mt-md-5,\n .my-md-5 {\n margin-top: 3rem !important;\n }\n .mr-md-5,\n .mx-md-5 {\n margin-right: 3rem !important;\n }\n .mb-md-5,\n .my-md-5 {\n margin-bottom: 3rem !important;\n }\n .ml-md-5,\n .mx-md-5 {\n margin-left: 3rem !important;\n }\n .p-md-0 {\n padding: 0 !important;\n }\n .pt-md-0,\n .py-md-0 {\n padding-top: 0 !important;\n }\n .pr-md-0,\n .px-md-0 {\n padding-right: 0 !important;\n }\n .pb-md-0,\n .py-md-0 {\n padding-bottom: 0 !important;\n }\n .pl-md-0,\n .px-md-0 {\n padding-left: 0 !important;\n }\n .p-md-1 {\n padding: 0.25rem !important;\n }\n .pt-md-1,\n .py-md-1 {\n padding-top: 0.25rem !important;\n }\n .pr-md-1,\n .px-md-1 {\n padding-right: 0.25rem !important;\n }\n .pb-md-1,\n .py-md-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-md-1,\n .px-md-1 {\n padding-left: 0.25rem !important;\n }\n .p-md-2 {\n padding: 0.5rem !important;\n }\n .pt-md-2,\n .py-md-2 {\n padding-top: 0.5rem !important;\n }\n .pr-md-2,\n .px-md-2 {\n padding-right: 0.5rem !important;\n }\n .pb-md-2,\n .py-md-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-md-2,\n .px-md-2 {\n padding-left: 0.5rem !important;\n }\n .p-md-3 {\n padding: 1rem !important;\n }\n .pt-md-3,\n .py-md-3 {\n padding-top: 1rem !important;\n }\n .pr-md-3,\n .px-md-3 {\n padding-right: 1rem !important;\n }\n .pb-md-3,\n .py-md-3 {\n padding-bottom: 1rem !important;\n }\n .pl-md-3,\n .px-md-3 {\n padding-left: 1rem !important;\n }\n .p-md-4 {\n padding: 1.5rem !important;\n }\n .pt-md-4,\n .py-md-4 {\n padding-top: 1.5rem !important;\n }\n .pr-md-4,\n .px-md-4 {\n padding-right: 1.5rem !important;\n }\n .pb-md-4,\n .py-md-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-md-4,\n .px-md-4 {\n padding-left: 1.5rem !important;\n }\n .p-md-5 {\n padding: 3rem !important;\n }\n .pt-md-5,\n .py-md-5 {\n padding-top: 3rem !important;\n }\n .pr-md-5,\n .px-md-5 {\n padding-right: 3rem !important;\n }\n .pb-md-5,\n .py-md-5 {\n padding-bottom: 3rem !important;\n }\n .pl-md-5,\n .px-md-5 {\n padding-left: 3rem !important;\n }\n .m-md-n1 {\n margin: -0.25rem !important;\n }\n .mt-md-n1,\n .my-md-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-md-n1,\n .mx-md-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-md-n1,\n .my-md-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-md-n1,\n .mx-md-n1 {\n margin-left: -0.25rem !important;\n }\n .m-md-n2 {\n margin: -0.5rem !important;\n }\n .mt-md-n2,\n .my-md-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-md-n2,\n .mx-md-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-md-n2,\n .my-md-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-md-n2,\n .mx-md-n2 {\n margin-left: -0.5rem !important;\n }\n .m-md-n3 {\n margin: -1rem !important;\n }\n .mt-md-n3,\n .my-md-n3 {\n margin-top: -1rem !important;\n }\n .mr-md-n3,\n .mx-md-n3 {\n margin-right: -1rem !important;\n }\n .mb-md-n3,\n .my-md-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-md-n3,\n .mx-md-n3 {\n margin-left: -1rem !important;\n }\n .m-md-n4 {\n margin: -1.5rem !important;\n }\n .mt-md-n4,\n .my-md-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-md-n4,\n .mx-md-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-md-n4,\n .my-md-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-md-n4,\n .mx-md-n4 {\n margin-left: -1.5rem !important;\n }\n .m-md-n5 {\n margin: -3rem !important;\n }\n .mt-md-n5,\n .my-md-n5 {\n margin-top: -3rem !important;\n }\n .mr-md-n5,\n .mx-md-n5 {\n margin-right: -3rem !important;\n }\n .mb-md-n5,\n .my-md-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-md-n5,\n .mx-md-n5 {\n margin-left: -3rem !important;\n }\n .m-md-auto {\n margin: auto !important;\n }\n .mt-md-auto,\n .my-md-auto {\n margin-top: auto !important;\n }\n .mr-md-auto,\n .mx-md-auto {\n margin-right: auto !important;\n }\n .mb-md-auto,\n .my-md-auto {\n margin-bottom: auto !important;\n }\n .ml-md-auto,\n .mx-md-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 992px) {\n .m-lg-0 {\n margin: 0 !important;\n }\n .mt-lg-0,\n .my-lg-0 {\n margin-top: 0 !important;\n }\n .mr-lg-0,\n .mx-lg-0 {\n margin-right: 0 !important;\n }\n .mb-lg-0,\n .my-lg-0 {\n margin-bottom: 0 !important;\n }\n .ml-lg-0,\n .mx-lg-0 {\n margin-left: 0 !important;\n }\n .m-lg-1 {\n margin: 0.25rem !important;\n }\n .mt-lg-1,\n .my-lg-1 {\n margin-top: 0.25rem !important;\n }\n .mr-lg-1,\n .mx-lg-1 {\n margin-right: 0.25rem !important;\n }\n .mb-lg-1,\n .my-lg-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-lg-1,\n .mx-lg-1 {\n margin-left: 0.25rem !important;\n }\n .m-lg-2 {\n margin: 0.5rem !important;\n }\n .mt-lg-2,\n .my-lg-2 {\n margin-top: 0.5rem !important;\n }\n .mr-lg-2,\n .mx-lg-2 {\n margin-right: 0.5rem !important;\n }\n .mb-lg-2,\n .my-lg-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-lg-2,\n .mx-lg-2 {\n margin-left: 0.5rem !important;\n }\n .m-lg-3 {\n margin: 1rem !important;\n }\n .mt-lg-3,\n .my-lg-3 {\n margin-top: 1rem !important;\n }\n .mr-lg-3,\n .mx-lg-3 {\n margin-right: 1rem !important;\n }\n .mb-lg-3,\n .my-lg-3 {\n margin-bottom: 1rem !important;\n }\n .ml-lg-3,\n .mx-lg-3 {\n margin-left: 1rem !important;\n }\n .m-lg-4 {\n margin: 1.5rem !important;\n }\n .mt-lg-4,\n .my-lg-4 {\n margin-top: 1.5rem !important;\n }\n .mr-lg-4,\n .mx-lg-4 {\n margin-right: 1.5rem !important;\n }\n .mb-lg-4,\n .my-lg-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-lg-4,\n .mx-lg-4 {\n margin-left: 1.5rem !important;\n }\n .m-lg-5 {\n margin: 3rem !important;\n }\n .mt-lg-5,\n .my-lg-5 {\n margin-top: 3rem !important;\n }\n .mr-lg-5,\n .mx-lg-5 {\n margin-right: 3rem !important;\n }\n .mb-lg-5,\n .my-lg-5 {\n margin-bottom: 3rem !important;\n }\n .ml-lg-5,\n .mx-lg-5 {\n margin-left: 3rem !important;\n }\n .p-lg-0 {\n padding: 0 !important;\n }\n .pt-lg-0,\n .py-lg-0 {\n padding-top: 0 !important;\n }\n .pr-lg-0,\n .px-lg-0 {\n padding-right: 0 !important;\n }\n .pb-lg-0,\n .py-lg-0 {\n padding-bottom: 0 !important;\n }\n .pl-lg-0,\n .px-lg-0 {\n padding-left: 0 !important;\n }\n .p-lg-1 {\n padding: 0.25rem !important;\n }\n .pt-lg-1,\n .py-lg-1 {\n padding-top: 0.25rem !important;\n }\n .pr-lg-1,\n .px-lg-1 {\n padding-right: 0.25rem !important;\n }\n .pb-lg-1,\n .py-lg-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-lg-1,\n .px-lg-1 {\n padding-left: 0.25rem !important;\n }\n .p-lg-2 {\n padding: 0.5rem !important;\n }\n .pt-lg-2,\n .py-lg-2 {\n padding-top: 0.5rem !important;\n }\n .pr-lg-2,\n .px-lg-2 {\n padding-right: 0.5rem !important;\n }\n .pb-lg-2,\n .py-lg-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-lg-2,\n .px-lg-2 {\n padding-left: 0.5rem !important;\n }\n .p-lg-3 {\n padding: 1rem !important;\n }\n .pt-lg-3,\n .py-lg-3 {\n padding-top: 1rem !important;\n }\n .pr-lg-3,\n .px-lg-3 {\n padding-right: 1rem !important;\n }\n .pb-lg-3,\n .py-lg-3 {\n padding-bottom: 1rem !important;\n }\n .pl-lg-3,\n .px-lg-3 {\n padding-left: 1rem !important;\n }\n .p-lg-4 {\n padding: 1.5rem !important;\n }\n .pt-lg-4,\n .py-lg-4 {\n padding-top: 1.5rem !important;\n }\n .pr-lg-4,\n .px-lg-4 {\n padding-right: 1.5rem !important;\n }\n .pb-lg-4,\n .py-lg-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-lg-4,\n .px-lg-4 {\n padding-left: 1.5rem !important;\n }\n .p-lg-5 {\n padding: 3rem !important;\n }\n .pt-lg-5,\n .py-lg-5 {\n padding-top: 3rem !important;\n }\n .pr-lg-5,\n .px-lg-5 {\n padding-right: 3rem !important;\n }\n .pb-lg-5,\n .py-lg-5 {\n padding-bottom: 3rem !important;\n }\n .pl-lg-5,\n .px-lg-5 {\n padding-left: 3rem !important;\n }\n .m-lg-n1 {\n margin: -0.25rem !important;\n }\n .mt-lg-n1,\n .my-lg-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-lg-n1,\n .mx-lg-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-lg-n1,\n .my-lg-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-lg-n1,\n .mx-lg-n1 {\n margin-left: -0.25rem !important;\n }\n .m-lg-n2 {\n margin: -0.5rem !important;\n }\n .mt-lg-n2,\n .my-lg-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-lg-n2,\n .mx-lg-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-lg-n2,\n .my-lg-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-lg-n2,\n .mx-lg-n2 {\n margin-left: -0.5rem !important;\n }\n .m-lg-n3 {\n margin: -1rem !important;\n }\n .mt-lg-n3,\n .my-lg-n3 {\n margin-top: -1rem !important;\n }\n .mr-lg-n3,\n .mx-lg-n3 {\n margin-right: -1rem !important;\n }\n .mb-lg-n3,\n .my-lg-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-lg-n3,\n .mx-lg-n3 {\n margin-left: -1rem !important;\n }\n .m-lg-n4 {\n margin: -1.5rem !important;\n }\n .mt-lg-n4,\n .my-lg-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-lg-n4,\n .mx-lg-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-lg-n4,\n .my-lg-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-lg-n4,\n .mx-lg-n4 {\n margin-left: -1.5rem !important;\n }\n .m-lg-n5 {\n margin: -3rem !important;\n }\n .mt-lg-n5,\n .my-lg-n5 {\n margin-top: -3rem !important;\n }\n .mr-lg-n5,\n .mx-lg-n5 {\n margin-right: -3rem !important;\n }\n .mb-lg-n5,\n .my-lg-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-lg-n5,\n .mx-lg-n5 {\n margin-left: -3rem !important;\n }\n .m-lg-auto {\n margin: auto !important;\n }\n .mt-lg-auto,\n .my-lg-auto {\n margin-top: auto !important;\n }\n .mr-lg-auto,\n .mx-lg-auto {\n margin-right: auto !important;\n }\n .mb-lg-auto,\n .my-lg-auto {\n margin-bottom: auto !important;\n }\n .ml-lg-auto,\n .mx-lg-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 1200px) {\n .m-xl-0 {\n margin: 0 !important;\n }\n .mt-xl-0,\n .my-xl-0 {\n margin-top: 0 !important;\n }\n .mr-xl-0,\n .mx-xl-0 {\n margin-right: 0 !important;\n }\n .mb-xl-0,\n .my-xl-0 {\n margin-bottom: 0 !important;\n }\n .ml-xl-0,\n .mx-xl-0 {\n margin-left: 0 !important;\n }\n .m-xl-1 {\n margin: 0.25rem !important;\n }\n .mt-xl-1,\n .my-xl-1 {\n margin-top: 0.25rem !important;\n }\n .mr-xl-1,\n .mx-xl-1 {\n margin-right: 0.25rem !important;\n }\n .mb-xl-1,\n .my-xl-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-xl-1,\n .mx-xl-1 {\n margin-left: 0.25rem !important;\n }\n .m-xl-2 {\n margin: 0.5rem !important;\n }\n .mt-xl-2,\n .my-xl-2 {\n margin-top: 0.5rem !important;\n }\n .mr-xl-2,\n .mx-xl-2 {\n margin-right: 0.5rem !important;\n }\n .mb-xl-2,\n .my-xl-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-xl-2,\n .mx-xl-2 {\n margin-left: 0.5rem !important;\n }\n .m-xl-3 {\n margin: 1rem !important;\n }\n .mt-xl-3,\n .my-xl-3 {\n margin-top: 1rem !important;\n }\n .mr-xl-3,\n .mx-xl-3 {\n margin-right: 1rem !important;\n }\n .mb-xl-3,\n .my-xl-3 {\n margin-bottom: 1rem !important;\n }\n .ml-xl-3,\n .mx-xl-3 {\n margin-left: 1rem !important;\n }\n .m-xl-4 {\n margin: 1.5rem !important;\n }\n .mt-xl-4,\n .my-xl-4 {\n margin-top: 1.5rem !important;\n }\n .mr-xl-4,\n .mx-xl-4 {\n margin-right: 1.5rem !important;\n }\n .mb-xl-4,\n .my-xl-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-xl-4,\n .mx-xl-4 {\n margin-left: 1.5rem !important;\n }\n .m-xl-5 {\n margin: 3rem !important;\n }\n .mt-xl-5,\n .my-xl-5 {\n margin-top: 3rem !important;\n }\n .mr-xl-5,\n .mx-xl-5 {\n margin-right: 3rem !important;\n }\n .mb-xl-5,\n .my-xl-5 {\n margin-bottom: 3rem !important;\n }\n .ml-xl-5,\n .mx-xl-5 {\n margin-left: 3rem !important;\n }\n .p-xl-0 {\n padding: 0 !important;\n }\n .pt-xl-0,\n .py-xl-0 {\n padding-top: 0 !important;\n }\n .pr-xl-0,\n .px-xl-0 {\n padding-right: 0 !important;\n }\n .pb-xl-0,\n .py-xl-0 {\n padding-bottom: 0 !important;\n }\n .pl-xl-0,\n .px-xl-0 {\n padding-left: 0 !important;\n }\n .p-xl-1 {\n padding: 0.25rem !important;\n }\n .pt-xl-1,\n .py-xl-1 {\n padding-top: 0.25rem !important;\n }\n .pr-xl-1,\n .px-xl-1 {\n padding-right: 0.25rem !important;\n }\n .pb-xl-1,\n .py-xl-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-xl-1,\n .px-xl-1 {\n padding-left: 0.25rem !important;\n }\n .p-xl-2 {\n padding: 0.5rem !important;\n }\n .pt-xl-2,\n .py-xl-2 {\n padding-top: 0.5rem !important;\n }\n .pr-xl-2,\n .px-xl-2 {\n padding-right: 0.5rem !important;\n }\n .pb-xl-2,\n .py-xl-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-xl-2,\n .px-xl-2 {\n padding-left: 0.5rem !important;\n }\n .p-xl-3 {\n padding: 1rem !important;\n }\n .pt-xl-3,\n .py-xl-3 {\n padding-top: 1rem !important;\n }\n .pr-xl-3,\n .px-xl-3 {\n padding-right: 1rem !important;\n }\n .pb-xl-3,\n .py-xl-3 {\n padding-bottom: 1rem !important;\n }\n .pl-xl-3,\n .px-xl-3 {\n padding-left: 1rem !important;\n }\n .p-xl-4 {\n padding: 1.5rem !important;\n }\n .pt-xl-4,\n .py-xl-4 {\n padding-top: 1.5rem !important;\n }\n .pr-xl-4,\n .px-xl-4 {\n padding-right: 1.5rem !important;\n }\n .pb-xl-4,\n .py-xl-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-xl-4,\n .px-xl-4 {\n padding-left: 1.5rem !important;\n }\n .p-xl-5 {\n padding: 3rem !important;\n }\n .pt-xl-5,\n .py-xl-5 {\n padding-top: 3rem !important;\n }\n .pr-xl-5,\n .px-xl-5 {\n padding-right: 3rem !important;\n }\n .pb-xl-5,\n .py-xl-5 {\n padding-bottom: 3rem !important;\n }\n .pl-xl-5,\n .px-xl-5 {\n padding-left: 3rem !important;\n }\n .m-xl-n1 {\n margin: -0.25rem !important;\n }\n .mt-xl-n1,\n .my-xl-n1 {\n margin-top: -0.25rem !important;\n }\n .mr-xl-n1,\n .mx-xl-n1 {\n margin-right: -0.25rem !important;\n }\n .mb-xl-n1,\n .my-xl-n1 {\n margin-bottom: -0.25rem !important;\n }\n .ml-xl-n1,\n .mx-xl-n1 {\n margin-left: -0.25rem !important;\n }\n .m-xl-n2 {\n margin: -0.5rem !important;\n }\n .mt-xl-n2,\n .my-xl-n2 {\n margin-top: -0.5rem !important;\n }\n .mr-xl-n2,\n .mx-xl-n2 {\n margin-right: -0.5rem !important;\n }\n .mb-xl-n2,\n .my-xl-n2 {\n margin-bottom: -0.5rem !important;\n }\n .ml-xl-n2,\n .mx-xl-n2 {\n margin-left: -0.5rem !important;\n }\n .m-xl-n3 {\n margin: -1rem !important;\n }\n .mt-xl-n3,\n .my-xl-n3 {\n margin-top: -1rem !important;\n }\n .mr-xl-n3,\n .mx-xl-n3 {\n margin-right: -1rem !important;\n }\n .mb-xl-n3,\n .my-xl-n3 {\n margin-bottom: -1rem !important;\n }\n .ml-xl-n3,\n .mx-xl-n3 {\n margin-left: -1rem !important;\n }\n .m-xl-n4 {\n margin: -1.5rem !important;\n }\n .mt-xl-n4,\n .my-xl-n4 {\n margin-top: -1.5rem !important;\n }\n .mr-xl-n4,\n .mx-xl-n4 {\n margin-right: -1.5rem !important;\n }\n .mb-xl-n4,\n .my-xl-n4 {\n margin-bottom: -1.5rem !important;\n }\n .ml-xl-n4,\n .mx-xl-n4 {\n margin-left: -1.5rem !important;\n }\n .m-xl-n5 {\n margin: -3rem !important;\n }\n .mt-xl-n5,\n .my-xl-n5 {\n margin-top: -3rem !important;\n }\n .mr-xl-n5,\n .mx-xl-n5 {\n margin-right: -3rem !important;\n }\n .mb-xl-n5,\n .my-xl-n5 {\n margin-bottom: -3rem !important;\n }\n .ml-xl-n5,\n .mx-xl-n5 {\n margin-left: -3rem !important;\n }\n .m-xl-auto {\n margin: auto !important;\n }\n .mt-xl-auto,\n .my-xl-auto {\n margin-top: auto !important;\n }\n .mr-xl-auto,\n .mx-xl-auto {\n margin-right: auto !important;\n }\n .mb-xl-auto,\n .my-xl-auto {\n margin-bottom: auto !important;\n }\n .ml-xl-auto,\n .mx-xl-auto {\n margin-left: auto !important;\n }\n}\n/*# sourceMappingURL=bootstrap-grid.css.map */","// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n@if $enable-grid-classes {\n // Single container class with breakpoint max-widths\n .container {\n @include make-container();\n @include make-container-max-widths();\n }\n\n // 100% wide container at all breakpoints\n .container-fluid {\n @include make-container();\n }\n\n // Responsive containers that are 100% wide until a breakpoint\n @each $breakpoint, $container-max-width in $container-max-widths {\n .container-#{$breakpoint} {\n @extend .container-fluid;\n }\n\n @include media-breakpoint-up($breakpoint, $grid-breakpoints) {\n %responsive-container-#{$breakpoint} {\n max-width: $container-max-width;\n }\n\n // Extend each breakpoint which is smaller or equal to the current breakpoint\n $extend-breakpoint: true;\n\n @each $name, $width in $grid-breakpoints {\n @if ($extend-breakpoint) {\n .container#{breakpoint-infix($name, $grid-breakpoints)} {\n @extend %responsive-container-#{$breakpoint};\n }\n\n // Once the current breakpoint is reached, stop extending\n @if ($breakpoint == $name) {\n $extend-breakpoint: false;\n }\n }\n }\n }\n }\n}\n\n\n// Row\n//\n// Rows contain your columns.\n\n@if $enable-grid-classes {\n .row {\n @include make-row();\n }\n\n // Remove the negative margin from default .row, then the horizontal padding\n // from all immediate children columns (to prevent runaway style inheritance).\n .no-gutters {\n margin-right: 0;\n margin-left: 0;\n\n > .col,\n > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n }\n }\n}\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n@if $enable-grid-classes {\n @include make-grid-columns();\n}\n","/// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n@mixin make-container($gutter: $grid-gutter-width) {\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n margin-right: auto;\n margin-left: auto;\n}\n\n\n// For each breakpoint, define the maximum width of the container in a media query\n@mixin make-container-max-widths($max-widths: $container-max-widths, $breakpoints: $grid-breakpoints) {\n @each $breakpoint, $container-max-width in $max-widths {\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n max-width: $container-max-width;\n }\n }\n}\n\n@mixin make-row($gutter: $grid-gutter-width) {\n display: flex;\n flex-wrap: wrap;\n margin-right: -$gutter / 2;\n margin-left: -$gutter / 2;\n}\n\n@mixin make-col-ready($gutter: $grid-gutter-width) {\n position: relative;\n // Prevent columns from becoming too narrow when at smaller grid tiers by\n // always setting `width: 100%;`. This works because we use `flex` values\n // later on to override this initial width.\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n}\n\n@mixin make-col($size, $columns: $grid-columns) {\n flex: 0 0 percentage($size / $columns);\n // Add a `max-width` to ensure content within each column does not blow out\n // the width of the column. Applies to IE10+ and Firefox. Chrome and Safari\n // do not appear to require this.\n max-width: percentage($size / $columns);\n}\n\n@mixin make-col-auto() {\n flex: 0 0 auto;\n width: auto;\n max-width: 100%; // Reset earlier grid tiers\n}\n\n@mixin make-col-offset($size, $columns: $grid-columns) {\n $num: $size / $columns;\n margin-left: if($num == 0, 0, percentage($num));\n}\n\n// Row columns\n//\n// Specify on a parent element(e.g., .row) to force immediate children into NN\n// numberof columns. Supports wrapping to new lines, but does not do a Masonry\n// style grid.\n@mixin row-cols($count) {\n & > * {\n flex: 0 0 100% / $count;\n max-width: 100% / $count;\n }\n}\n","// Breakpoint viewport sizes and media queries.\n//\n// Breakpoints are defined as a map of (name: minimum width), order from small to large:\n//\n// (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)\n//\n// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.\n\n// Name of the next breakpoint, or null for the last breakpoint.\n//\n// >> breakpoint-next(sm)\n// md\n// >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// md\n// >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl))\n// md\n@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {\n $n: index($breakpoint-names, $name);\n @return if($n != null and $n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);\n}\n\n// Minimum breakpoint width. Null for the smallest (first) breakpoint.\n//\n// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 576px\n@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {\n $min: map-get($breakpoints, $name);\n @return if($min != 0, $min, null);\n}\n\n// Maximum breakpoint width. Null for the largest (last) breakpoint.\n// The maximum value is calculated as the minimum of the next one less 0.02px\n// to work around the limitations of `min-` and `max-` prefixes and viewports with fractional widths.\n// See https://www.w3.org/TR/mediaqueries-4/#mq-min-max\n// Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari.\n// See https://bugs.webkit.org/show_bug.cgi?id=178261\n//\n// >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 767.98px\n@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {\n $next: breakpoint-next($name, $breakpoints);\n @return if($next, breakpoint-min($next, $breakpoints) - .02, null);\n}\n\n// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash in front.\n// Useful for making responsive utilities.\n//\n// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"\" (Returns a blank string)\n// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"-sm\"\n@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {\n @return if(breakpoint-min($name, $breakpoints) == null, \"\", \"-#{$name}\");\n}\n\n// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.\n// Makes the @content apply to the given breakpoint and wider.\n@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n @if $min {\n @media (min-width: $min) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media of at most the maximum breakpoint width. No query for the largest breakpoint.\n// Makes the @content apply to the given breakpoint and narrower.\n@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {\n $max: breakpoint-max($name, $breakpoints);\n @if $max {\n @media (max-width: $max) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media that spans multiple breakpoint widths.\n// Makes the @content apply between the min and max breakpoints\n@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($lower, $breakpoints);\n $max: breakpoint-max($upper, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($lower, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($upper, $breakpoints) {\n @content;\n }\n }\n}\n\n// Media between the breakpoint's minimum and maximum widths.\n// No minimum for the smallest breakpoint, and no maximum for the largest one.\n// Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.\n@mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n $max: breakpoint-max($name, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($name, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($name, $breakpoints) {\n @content;\n }\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `$grid-columns`.\n\n@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) {\n // Common properties for all breakpoints\n %grid-column {\n position: relative;\n width: 100%;\n padding-right: $gutter / 2;\n padding-left: $gutter / 2;\n }\n\n @each $breakpoint in map-keys($breakpoints) {\n $infix: breakpoint-infix($breakpoint, $breakpoints);\n\n @if $columns > 0 {\n // Allow columns to stretch full width below their breakpoints\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @extend %grid-column;\n }\n }\n }\n\n .col#{$infix},\n .col#{$infix}-auto {\n @extend %grid-column;\n }\n\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n // Provide basic `.col-{bp}` classes for equal-width flexbox columns\n .col#{$infix} {\n flex-basis: 0;\n flex-grow: 1;\n min-width: 0; // See https://github.com/twbs/bootstrap/issues/25410\n max-width: 100%;\n }\n\n @if $grid-row-columns > 0 {\n @for $i from 1 through $grid-row-columns {\n .row-cols#{$infix}-#{$i} {\n @include row-cols($i);\n }\n }\n }\n\n .col#{$infix}-auto {\n @include make-col-auto();\n }\n\n @if $columns > 0 {\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @include make-col($i, $columns);\n }\n }\n }\n\n .order#{$infix}-first { order: -1; }\n\n .order#{$infix}-last { order: $columns + 1; }\n\n @for $i from 0 through $columns {\n .order#{$infix}-#{$i} { order: $i; }\n }\n\n @if $columns > 0 {\n // `$columns - 1` because offsetting by the width of an entire row isn't possible\n @for $i from 0 through ($columns - 1) {\n @if not ($infix == \"\" and $i == 0) { // Avoid emitting useless .offset-0\n .offset#{$infix}-#{$i} {\n @include make-col-offset($i, $columns);\n }\n }\n }\n }\n }\n }\n}\n","// stylelint-disable declaration-no-important\n\n//\n// Utilities for common `display` values\n//\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n @each $value in $displays {\n .d#{$infix}-#{$value} { display: $value !important; }\n }\n }\n}\n\n\n//\n// Utilities for toggling `display` in print\n//\n\n@media print {\n @each $value in $displays {\n .d-print-#{$value} { display: $value !important; }\n }\n}\n","// stylelint-disable declaration-no-important\n\n// Flex variation\n//\n// Custom styles for additional flex alignment options.\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n .flex#{$infix}-row { flex-direction: row !important; }\n .flex#{$infix}-column { flex-direction: column !important; }\n .flex#{$infix}-row-reverse { flex-direction: row-reverse !important; }\n .flex#{$infix}-column-reverse { flex-direction: column-reverse !important; }\n\n .flex#{$infix}-wrap { flex-wrap: wrap !important; }\n .flex#{$infix}-nowrap { flex-wrap: nowrap !important; }\n .flex#{$infix}-wrap-reverse { flex-wrap: wrap-reverse !important; }\n .flex#{$infix}-fill { flex: 1 1 auto !important; }\n .flex#{$infix}-grow-0 { flex-grow: 0 !important; }\n .flex#{$infix}-grow-1 { flex-grow: 1 !important; }\n .flex#{$infix}-shrink-0 { flex-shrink: 0 !important; }\n .flex#{$infix}-shrink-1 { flex-shrink: 1 !important; }\n\n .justify-content#{$infix}-start { justify-content: flex-start !important; }\n .justify-content#{$infix}-end { justify-content: flex-end !important; }\n .justify-content#{$infix}-center { justify-content: center !important; }\n .justify-content#{$infix}-between { justify-content: space-between !important; }\n .justify-content#{$infix}-around { justify-content: space-around !important; }\n\n .align-items#{$infix}-start { align-items: flex-start !important; }\n .align-items#{$infix}-end { align-items: flex-end !important; }\n .align-items#{$infix}-center { align-items: center !important; }\n .align-items#{$infix}-baseline { align-items: baseline !important; }\n .align-items#{$infix}-stretch { align-items: stretch !important; }\n\n .align-content#{$infix}-start { align-content: flex-start !important; }\n .align-content#{$infix}-end { align-content: flex-end !important; }\n .align-content#{$infix}-center { align-content: center !important; }\n .align-content#{$infix}-between { align-content: space-between !important; }\n .align-content#{$infix}-around { align-content: space-around !important; }\n .align-content#{$infix}-stretch { align-content: stretch !important; }\n\n .align-self#{$infix}-auto { align-self: auto !important; }\n .align-self#{$infix}-start { align-self: flex-start !important; }\n .align-self#{$infix}-end { align-self: flex-end !important; }\n .align-self#{$infix}-center { align-self: center !important; }\n .align-self#{$infix}-baseline { align-self: baseline !important; }\n .align-self#{$infix}-stretch { align-self: stretch !important; }\n }\n}\n","// stylelint-disable declaration-no-important\n\n// Margin and Padding\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n @each $prop, $abbrev in (margin: m, padding: p) {\n @each $size, $length in $spacers {\n .#{$abbrev}#{$infix}-#{$size} { #{$prop}: $length !important; }\n .#{$abbrev}t#{$infix}-#{$size},\n .#{$abbrev}y#{$infix}-#{$size} {\n #{$prop}-top: $length !important;\n }\n .#{$abbrev}r#{$infix}-#{$size},\n .#{$abbrev}x#{$infix}-#{$size} {\n #{$prop}-right: $length !important;\n }\n .#{$abbrev}b#{$infix}-#{$size},\n .#{$abbrev}y#{$infix}-#{$size} {\n #{$prop}-bottom: $length !important;\n }\n .#{$abbrev}l#{$infix}-#{$size},\n .#{$abbrev}x#{$infix}-#{$size} {\n #{$prop}-left: $length !important;\n }\n }\n }\n\n // Negative margins (e.g., where `.mb-n1` is negative version of `.mb-1`)\n @each $size, $length in $spacers {\n @if $size != 0 {\n .m#{$infix}-n#{$size} { margin: -$length !important; }\n .mt#{$infix}-n#{$size},\n .my#{$infix}-n#{$size} {\n margin-top: -$length !important;\n }\n .mr#{$infix}-n#{$size},\n .mx#{$infix}-n#{$size} {\n margin-right: -$length !important;\n }\n .mb#{$infix}-n#{$size},\n .my#{$infix}-n#{$size} {\n margin-bottom: -$length !important;\n }\n .ml#{$infix}-n#{$size},\n .mx#{$infix}-n#{$size} {\n margin-left: -$length !important;\n }\n }\n }\n\n // Some special margin utils\n .m#{$infix}-auto { margin: auto !important; }\n .mt#{$infix}-auto,\n .my#{$infix}-auto {\n margin-top: auto !important;\n }\n .mr#{$infix}-auto,\n .mx#{$infix}-auto {\n margin-right: auto !important;\n }\n .mb#{$infix}-auto,\n .my#{$infix}-auto {\n margin-bottom: auto !important;\n }\n .ml#{$infix}-auto,\n .mx#{$infix}-auto {\n margin-left: auto !important;\n }\n }\n}\n"]} \ No newline at end of file diff --git a/assets/ext/bootstrap/css/bootstrap-reboot.css b/assets/ext/bootstrap/css/bootstrap-reboot.css new file mode 100644 index 00000000..aa9fd2be --- /dev/null +++ b/assets/ext/bootstrap/css/bootstrap-reboot.css @@ -0,0 +1,325 @@ +/*! + * Bootstrap Reboot v4.5.0 (https://getbootstrap.com/) + * Copyright 2011-2020 The Bootstrap Authors + * Copyright 2011-2020 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) + */ +*, +*::before, +*::after { + box-sizing: border-box; +} + +html { + font-family: sans-serif; + line-height: 1.15; + -webkit-text-size-adjust: 100%; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} + +article, aside, figcaption, figure, footer, header, hgroup, main, nav, section { + display: block; +} + +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + text-align: left; + background-color: #fff; +} + +[tabindex="-1"]:focus:not(:focus-visible) { + outline: 0 !important; +} + +hr { + box-sizing: content-box; + height: 0; + overflow: visible; +} + +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 0.5rem; +} + +p { + margin-top: 0; + margin-bottom: 1rem; +} + +abbr[title], +abbr[data-original-title] { + text-decoration: underline; + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; + cursor: help; + border-bottom: 0; + -webkit-text-decoration-skip-ink: none; + text-decoration-skip-ink: none; +} + +address { + margin-bottom: 1rem; + font-style: normal; + line-height: inherit; +} + +ol, +ul, +dl { + margin-top: 0; + margin-bottom: 1rem; +} + +ol ol, +ul ul, +ol ul, +ul ol { + margin-bottom: 0; +} + +dt { + font-weight: 700; +} + +dd { + margin-bottom: .5rem; + margin-left: 0; +} + +blockquote { + margin: 0 0 1rem; +} + +b, +strong { + font-weight: bolder; +} + +small { + font-size: 80%; +} + +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} + +sub { + bottom: -.25em; +} + +sup { + top: -.5em; +} + +a { + color: #007bff; + text-decoration: none; + background-color: transparent; +} + +a:hover { + color: #0056b3; + text-decoration: underline; +} + +a:not([href]) { + color: inherit; + text-decoration: none; +} + +a:not([href]):hover { + color: inherit; + text-decoration: none; +} + +pre, +code, +kbd, +samp { + font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + font-size: 1em; +} + +pre { + margin-top: 0; + margin-bottom: 1rem; + overflow: auto; + -ms-overflow-style: scrollbar; +} + +figure { + margin: 0 0 1rem; +} + +img { + vertical-align: middle; + border-style: none; +} + +svg { + overflow: hidden; + vertical-align: middle; +} + +table { + border-collapse: collapse; +} + +caption { + padding-top: 0.75rem; + padding-bottom: 0.75rem; + color: #6c757d; + text-align: left; + caption-side: bottom; +} + +th { + text-align: inherit; +} + +label { + display: inline-block; + margin-bottom: 0.5rem; +} + +button { + border-radius: 0; +} + +button:focus { + outline: 1px dotted; + outline: 5px auto -webkit-focus-ring-color; +} + +input, +button, +select, +optgroup, +textarea { + margin: 0; + font-family: inherit; + font-size: inherit; + line-height: inherit; +} + +button, +input { + overflow: visible; +} + +button, +select { + text-transform: none; +} + +[role="button"] { + cursor: pointer; +} + +select { + word-wrap: normal; +} + +button, +[type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; +} + +button:not(:disabled), +[type="button"]:not(:disabled), +[type="reset"]:not(:disabled), +[type="submit"]:not(:disabled) { + cursor: pointer; +} + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + padding: 0; + border-style: none; +} + +input[type="radio"], +input[type="checkbox"] { + box-sizing: border-box; + padding: 0; +} + +textarea { + overflow: auto; + resize: vertical; +} + +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} + +legend { + display: block; + width: 100%; + max-width: 100%; + padding: 0; + margin-bottom: .5rem; + font-size: 1.5rem; + line-height: inherit; + color: inherit; + white-space: normal; +} + +progress { + vertical-align: baseline; +} + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +[type="search"] { + outline-offset: -2px; + -webkit-appearance: none; +} + +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +::-webkit-file-upload-button { + font: inherit; + -webkit-appearance: button; +} + +output { + display: inline-block; +} + +summary { + display: list-item; + cursor: pointer; +} + +template { + display: none; +} + +[hidden] { + display: none !important; +} +/*# sourceMappingURL=bootstrap-reboot.css.map */ \ No newline at end of file diff --git a/assets/ext/bootstrap/css/bootstrap-reboot.css.map b/assets/ext/bootstrap/css/bootstrap-reboot.css.map new file mode 100644 index 00000000..5d3e152c --- /dev/null +++ b/assets/ext/bootstrap/css/bootstrap-reboot.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../scss/bootstrap-reboot.scss","bootstrap-reboot.css","../../scss/_reboot.scss","../../scss/_variables.scss","../../scss/vendor/_rfs.scss","../../scss/mixins/_hover.scss"],"names":[],"mappings":"AAAA;;;;;;ECME;ACYF;;;EAGE,sBAAsB;ADVxB;;ACaA;EACE,uBAAuB;EACvB,iBAAiB;EACjB,8BAA8B;EAC9B,6CCXa;AFCf;;ACgBA;EACE,cAAc;ADbhB;;ACuBA;EACE,SAAS;EACT,kMC2OiN;EC3J7M,eAtCY;EFxChB,gBCoP+B;EDnP/B,gBCwP+B;EDvP/B,cCnCgB;EDoChB,gBAAgB;EAChB,sBC9Ca;AF0Bf;;AAEA;EC+BE,qBAAqB;AD7BvB;;ACsCA;EACE,uBAAuB;EACvB,SAAS;EACT,iBAAiB;ADnCnB;;ACgDA;EACE,aAAa;EACb,qBCsNuC;AFnQzC;;ACoDA;EACE,aAAa;EACb,mBCyF8B;AF1IhC;;AC4DA;;EAEE,0BAA0B;EAC1B,yCAAiC;EAAjC,iCAAiC;EACjC,YAAY;EACZ,gBAAgB;EAChB,sCAA8B;EAA9B,8BAA8B;ADzDhC;;AC4DA;EACE,mBAAmB;EACnB,kBAAkB;EAClB,oBAAoB;ADzDtB;;AC4DA;;;EAGE,aAAa;EACb,mBAAmB;ADzDrB;;AC4DA;;;;EAIE,gBAAgB;ADzDlB;;AC4DA;EACE,gBCuJ+B;AFhNjC;;AC4DA;EACE,oBAAoB;EACpB,cAAc;ADzDhB;;AC4DA;EACE,gBAAgB;ADzDlB;;AC4DA;;EAEE,mBC0IkC;AFnMpC;;AC4DA;EExFI,cAAW;AHgCf;;ACiEA;;EAEE,kBAAkB;EEnGhB,cAAW;EFqGb,cAAc;EACd,wBAAwB;AD9D1B;;ACiEA;EAAM,cAAc;AD7DpB;;AC8DA;EAAM,UAAU;AD1DhB;;ACiEA;EACE,cCtJe;EDuJf,qBCN4C;EDO5C,6BAA6B;AD9D/B;;AIlHE;EHmLE,cCT8D;EDU9D,0BCT+C;AFpDnD;;ACsEA;EACE,cAAc;EACd,qBAAqB;ADnEvB;;AI5HE;EHkME,cAAc;EACd,qBAAqB;ADlEzB;;AC2EA;;;;EAIE,iGC+DgH;ECnN9G,cAAW;AH6Ef;;AC2EA;EAEE,aAAa;EAEb,mBAAmB;EAEnB,cAAc;EAGd,6BAA6B;AD7E/B;;ACqFA;EAEE,gBAAgB;ADnFlB;;AC2FA;EACE,sBAAsB;EACtB,kBAAkB;ADxFpB;;AC2FA;EAGE,gBAAgB;EAChB,sBAAsB;AD1FxB;;ACkGA;EACE,yBAAyB;AD/F3B;;ACkGA;EACE,oBCmFkC;EDlFlC,uBCkFkC;EDjFlC,cCtQgB;EDuQhB,gBAAgB;EAChB,oBAAoB;AD/FtB;;ACkGA;EAGE,mBAAmB;ADjGrB;;ACyGA;EAEE,qBAAqB;EACrB,qBCoK2C;AF3Q7C;;AC6GA;EAEE,gBAAgB;AD3GlB;;ACkHA;EACE,mBAAmB;EACnB,0CAA0C;AD/G5C;;ACkHA;;;;;EAKE,SAAS;EACT,oBAAoB;EExPlB,kBAAW;EF0Pb,oBAAoB;AD/GtB;;ACkHA;;EAEE,iBAAiB;AD/GnB;;ACkHA;;EAEE,oBAAoB;AD/GtB;;AAEA;ECoHE,eAAe;ADlHjB;;ACwHA;EACE,iBAAiB;ADrHnB;;AC4HA;;;;EAIE,0BAA0B;ADzH5B;;AC8HE;;;;EAKI,eAAe;AD5HrB;;ACkIA;;;;EAIE,UAAU;EACV,kBAAkB;AD/HpB;;ACkIA;;EAEE,sBAAsB;EACtB,UAAU;AD/HZ;;ACmIA;EACE,cAAc;EAEd,gBAAgB;ADjIlB;;ACoIA;EAME,YAAY;EAEZ,UAAU;EACV,SAAS;EACT,SAAS;ADvIX;;AC4IA;EACE,cAAc;EACd,WAAW;EACX,eAAe;EACf,UAAU;EACV,oBAAoB;EE/RhB,iBAtCY;EFuUhB,oBAAoB;EACpB,cAAc;EACd,mBAAmB;ADzIrB;;AC4IA;EACE,wBAAwB;ADzI1B;;AAEA;;EC6IE,YAAY;AD1Id;;AAEA;ECgJE,oBAAoB;EACpB,wBAAwB;AD9I1B;;AAEA;ECoJE,wBAAwB;ADlJ1B;;AC0JA;EACE,aAAa;EACb,0BAA0B;ADvJ5B;;AC8JA;EACE,qBAAqB;AD3JvB;;AC8JA;EACE,kBAAkB;EAClB,eAAe;AD3JjB;;AC8JA;EACE,aAAa;AD3Jf;;AAEA;EC+JE,wBAAwB;AD7J1B","file":"bootstrap-reboot.css","sourcesContent":["/*!\n * Bootstrap Reboot v4.5.0 (https://getbootstrap.com/)\n * Copyright 2011-2020 The Bootstrap Authors\n * Copyright 2011-2020 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n\n@import \"functions\";\n@import \"variables\";\n@import \"mixins\";\n@import \"reboot\";\n","/*!\n * Bootstrap Reboot v4.5.0 (https://getbootstrap.com/)\n * Copyright 2011-2020 The Bootstrap Authors\n * Copyright 2011-2020 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nhtml {\n font-family: sans-serif;\n line-height: 1.15;\n -webkit-text-size-adjust: 100%;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\nbody {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #212529;\n text-align: left;\n background-color: #fff;\n}\n\n[tabindex=\"-1\"]:focus:not(:focus-visible) {\n outline: 0 !important;\n}\n\nhr {\n box-sizing: content-box;\n height: 0;\n overflow: visible;\n}\n\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: 0.5rem;\n}\n\np {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-original-title] {\n text-decoration: underline;\n text-decoration: underline dotted;\n cursor: help;\n border-bottom: 0;\n text-decoration-skip-ink: none;\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: 700;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0;\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\nb,\nstrong {\n font-weight: bolder;\n}\n\nsmall {\n font-size: 80%;\n}\n\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -.25em;\n}\n\nsup {\n top: -.5em;\n}\n\na {\n color: #007bff;\n text-decoration: none;\n background-color: transparent;\n}\n\na:hover {\n color: #0056b3;\n text-decoration: underline;\n}\n\na:not([href]) {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):hover {\n color: inherit;\n text-decoration: none;\n}\n\npre,\ncode,\nkbd,\nsamp {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 1em;\n}\n\npre {\n margin-top: 0;\n margin-bottom: 1rem;\n overflow: auto;\n -ms-overflow-style: scrollbar;\n}\n\nfigure {\n margin: 0 0 1rem;\n}\n\nimg {\n vertical-align: middle;\n border-style: none;\n}\n\nsvg {\n overflow: hidden;\n vertical-align: middle;\n}\n\ntable {\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n color: #6c757d;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n text-align: inherit;\n}\n\nlabel {\n display: inline-block;\n margin-bottom: 0.5rem;\n}\n\nbutton {\n border-radius: 0;\n}\n\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible;\n}\n\nbutton,\nselect {\n text-transform: none;\n}\n\n[role=\"button\"] {\n cursor: pointer;\n}\n\nselect {\n word-wrap: normal;\n}\n\nbutton,\n[type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\nbutton:not(:disabled),\n[type=\"button\"]:not(:disabled),\n[type=\"reset\"]:not(:disabled),\n[type=\"submit\"]:not(:disabled) {\n cursor: pointer;\n}\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box;\n padding: 0;\n}\n\ntextarea {\n overflow: auto;\n resize: vertical;\n}\n\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n max-width: 100%;\n padding: 0;\n margin-bottom: .5rem;\n font-size: 1.5rem;\n line-height: inherit;\n color: inherit;\n white-space: normal;\n}\n\nprogress {\n vertical-align: baseline;\n}\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n outline-offset: -2px;\n -webkit-appearance: none;\n}\n\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n::-webkit-file-upload-button {\n font: inherit;\n -webkit-appearance: button;\n}\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item;\n cursor: pointer;\n}\n\ntemplate {\n display: none;\n}\n\n[hidden] {\n display: none !important;\n}\n\n/*# sourceMappingURL=bootstrap-reboot.css.map */","// stylelint-disable at-rule-no-vendor-prefix, declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix\n\n// Reboot\n//\n// Normalization of HTML elements, manually forked from Normalize.css to remove\n// styles targeting irrelevant browsers while applying new styles.\n//\n// Normalize is licensed MIT. https://github.com/necolas/normalize.css\n\n\n// Document\n//\n// 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.\n// 2. Change the default font family in all browsers.\n// 3. Correct the line height in all browsers.\n// 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS.\n// 5. Change the default tap highlight to be completely transparent in iOS.\n\n*,\n*::before,\n*::after {\n box-sizing: border-box; // 1\n}\n\nhtml {\n font-family: sans-serif; // 2\n line-height: 1.15; // 3\n -webkit-text-size-adjust: 100%; // 4\n -webkit-tap-highlight-color: rgba($black, 0); // 5\n}\n\n// Shim for \"new\" HTML5 structural elements to display correctly (IE10, older browsers)\n// TODO: remove in v5\n// stylelint-disable-next-line selector-list-comma-newline-after\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\n// Body\n//\n// 1. Remove the margin in all browsers.\n// 2. As a best practice, apply a default `background-color`.\n// 3. Set an explicit initial text-align value so that we can later use\n// the `inherit` value on things like `` elements.\n\nbody {\n margin: 0; // 1\n font-family: $font-family-base;\n @include font-size($font-size-base);\n font-weight: $font-weight-base;\n line-height: $line-height-base;\n color: $body-color;\n text-align: left; // 3\n background-color: $body-bg; // 2\n}\n\n// Future-proof rule: in browsers that support :focus-visible, suppress the focus outline\n// on elements that programmatically receive focus but wouldn't normally show a visible\n// focus outline. In general, this would mean that the outline is only applied if the\n// interaction that led to the element receiving programmatic focus was a keyboard interaction,\n// or the browser has somehow determined that the user is primarily a keyboard user and/or\n// wants focus outlines to always be presented.\n//\n// See https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible\n// and https://developer.paciellogroup.com/blog/2018/03/focus-visible-and-backwards-compatibility/\n[tabindex=\"-1\"]:focus:not(:focus-visible) {\n outline: 0 !important;\n}\n\n\n// Content grouping\n//\n// 1. Add the correct box sizing in Firefox.\n// 2. Show the overflow in Edge and IE.\n\nhr {\n box-sizing: content-box; // 1\n height: 0; // 1\n overflow: visible; // 2\n}\n\n\n//\n// Typography\n//\n\n// Remove top margins from headings\n//\n// By default, `

`-`

` all receive top and bottom margins. We nuke the top\n// margin for easier control within type scales as it avoids margin collapsing.\n// stylelint-disable-next-line selector-list-comma-newline-after\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: $headings-margin-bottom;\n}\n\n// Reset margins on paragraphs\n//\n// Similarly, the top margin on `

`s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n// Abbreviations\n//\n// 1. Duplicate behavior to the data-* attribute for our tooltip plugin\n// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n// 3. Add explicit cursor to indicate changed behavior.\n// 4. Remove the bottom border in Firefox 39-.\n// 5. Prevent the text-decoration to be skipped.\n\nabbr[title],\nabbr[data-original-title] { // 1\n text-decoration: underline; // 2\n text-decoration: underline dotted; // 2\n cursor: help; // 3\n border-bottom: 0; // 4\n text-decoration-skip-ink: none; // 5\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // Undo browser default\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\nb,\nstrong {\n font-weight: $font-weight-bolder; // Add the correct font weight in Chrome, Edge, and Safari\n}\n\nsmall {\n @include font-size(80%); // Add the correct font size in all browsers\n}\n\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n//\n\nsub,\nsup {\n position: relative;\n @include font-size(75%);\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n//\n// Links\n//\n\na {\n color: $link-color;\n text-decoration: $link-decoration;\n background-color: transparent; // Remove the gray background on active links in IE 10.\n\n @include hover() {\n color: $link-hover-color;\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]) {\n color: inherit;\n text-decoration: none;\n\n @include hover() {\n color: inherit;\n text-decoration: none;\n }\n}\n\n\n//\n// Code\n//\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-monospace;\n @include font-size(1em); // Correct the odd `em` font sizing in all browsers.\n}\n\npre {\n // Remove browser default top margin\n margin-top: 0;\n // Reset browser default of `1em` to use `rem`s\n margin-bottom: 1rem;\n // Don't allow content to break outside\n overflow: auto;\n // Disable auto-hiding scrollbar in IE & legacy Edge to avoid overlap,\n // making it impossible to interact with the content\n -ms-overflow-style: scrollbar;\n}\n\n\n//\n// Figures\n//\n\nfigure {\n // Apply a consistent margin strategy (matches our type styles).\n margin: 0 0 1rem;\n}\n\n\n//\n// Images and content\n//\n\nimg {\n vertical-align: middle;\n border-style: none; // Remove the border on images inside links in IE 10-.\n}\n\nsvg {\n // Workaround for the SVG overflow bug in IE10/11 is still required.\n // See https://github.com/twbs/bootstrap/issues/26878\n overflow: hidden;\n vertical-align: middle;\n}\n\n\n//\n// Tables\n//\n\ntable {\n border-collapse: collapse; // Prevent double borders\n}\n\ncaption {\n padding-top: $table-cell-padding;\n padding-bottom: $table-cell-padding;\n color: $table-caption-color;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n // Matches default `` alignment by inheriting from the ``, or the\n // closest parent with a set `text-align`.\n text-align: inherit;\n}\n\n\n//\n// Forms\n//\n\nlabel {\n // Allow labels to use `margin` for spacing.\n display: inline-block;\n margin-bottom: $label-margin-bottom;\n}\n\n// Remove the default `border-radius` that macOS Chrome adds.\n//\n// Details at https://github.com/twbs/bootstrap/issues/24093\nbutton {\n // stylelint-disable-next-line property-blacklist\n border-radius: 0;\n}\n\n// Work around a Firefox/IE bug where the transparent `button` background\n// results in a loss of the default `button` focus styles.\n//\n// Credit: https://github.com/suitcss/base/\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0; // Remove the margin in Firefox and Safari\n font-family: inherit;\n @include font-size(inherit);\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible; // Show the overflow in Edge\n}\n\nbutton,\nselect {\n text-transform: none; // Remove the inheritance of text transform in Firefox\n}\n\n// Set the cursor for non-`").click(function(t){w.hasClass(o.getClass("stateDisabled"))||(g(t),(w.hasClass(o.getClass("stateActive"))||w.hasClass(o.getClass("stateDisabled")))&&w.removeClass(o.getClass("stateHover")))}).mousedown(function(){w.not("."+o.getClass("stateActive")).not("."+o.getClass("stateDisabled")).addClass(o.getClass("stateDown"))}).mouseup(function(){w.removeClass(o.getClass("stateDown"))}).hover(function(){w.not("."+o.getClass("stateActive")).not("."+o.getClass("stateDisabled")).addClass(o.getClass("stateHover"))},function(){w.removeClass(o.getClass("stateHover")).removeClass(o.getClass("stateDown"))}),h=h.add(w)))}),f&&h.first().addClass(o.getClass("cornerLeft")).end().last().addClass(o.getClass("cornerRight")).end(),h.length>1?(u=r("

"),f&&u.addClass(o.getClass("buttonGroup")),u.append(h),l.append(u)):l.append(h)}),l},t.prototype.updateTitle=function(t){this.el&&this.el.find("h2").text(t)},t.prototype.activateButton=function(t){this.el&&this.el.find(".fc-"+t+"-button").addClass(this.calendar.theme.getClass("stateActive"))},t.prototype.deactivateButton=function(t){this.el&&this.el.find(".fc-"+t+"-button").removeClass(this.calendar.theme.getClass("stateActive"))},t.prototype.disableButton=function(t){this.el&&this.el.find(".fc-"+t+"-button").prop("disabled",!0).addClass(this.calendar.theme.getClass("stateDisabled"))},t.prototype.enableButton=function(t){this.el&&this.el.find(".fc-"+t+"-button").prop("disabled",!1).removeClass(this.calendar.theme.getClass("stateDisabled"))},t.prototype.getViewsWithButtons=function(){return this.viewsWithButtons},t}();e.default=o},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var r=n(2),i=n(3),o=n(4),s=n(33),a=n(32),l=n(51),u=function(t){function e(e,n){var r=t.call(this)||this;return r._calendar=e,r.overrides=i.extend({},n),r.dynamicOverrides={},r.compute(),r}return r.__extends(e,t),e.prototype.add=function(t){var e,n=0;this.recordOverrides(t);for(e in t)n++;if(1===n){if("height"===e||"contentHeight"===e||"aspectRatio"===e)return void this._calendar.updateViewSize(!0);if("defaultDate"===e)return;if("businessHours"===e)return;if(/^(event|select)(Overlap|Constraint|Allow)$/.test(e))return;if("timezone"===e)return void this._calendar.view.flash("initialEvents")}this._calendar.renderHeader(),this._calendar.renderFooter(),this._calendar.viewsByType={},this._calendar.reinitView()},e.prototype.compute=function(){var t,e,n,r,i;t=o.firstDefined(this.dynamicOverrides.locale,this.overrides.locale),e=a.localeOptionHash[t],e||(t=s.globalDefaults.locale,e=a.localeOptionHash[t]||{}),n=o.firstDefined(this.dynamicOverrides.isRTL,this.overrides.isRTL,e.isRTL,s.globalDefaults.isRTL),r=n?s.rtlDefaults:{},this.dirDefaults=r,this.localeDefaults=e,i=s.mergeOptions([s.globalDefaults,r,e,this.overrides,this.dynamicOverrides]),a.populateInstanceComputableOptions(i),this.reset(i)},e.prototype.recordOverrides=function(t){var e;for(e in t)this.dynamicOverrides[e]=t[e];this._calendar.viewSpecManager.clearCache(),this.compute()},e}(l.default);e.default=u},function(t,e,n){Object.defineProperty(e,"__esModule",{value:!0});var r=n(0),i=n(3),o=n(24),s=n(4),a=n(33),l=n(32),u=function(){function t(t,e){this.optionsManager=t,this._calendar=e,this.clearCache()}return t.prototype.clearCache=function(){this.viewSpecCache={}},t.prototype.getViewSpec=function(t){var e=this.viewSpecCache;return e[t]||(e[t]=this.buildViewSpec(t))},t.prototype.getUnitViewSpec=function(t){var e,n,r;if(-1!==i.inArray(t,s.unitsDesc))for(e=this._calendar.header.getViewsWithButtons(),i.each(o.viewHash,function(t){e.push(t)}),n=0;n=20?"ste":"de")},week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(74);var n=t(1);n.datepickerLocale("ar-dz","ar-DZ",{closeText:"إغلاق",prevText:"<السابق",nextText:"التالي>",currentText:"اليوم",monthNames:["جانفي","فيفري","مارس","أفريل","ماي","جوان","جويلية","أوت","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],monthNamesShort:["1","2","3","4","5","6","7","8","9","10","11","12"],dayNames:["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت"],dayNamesShort:["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت"],dayNamesMin:["ح","ن","ث","ر","خ","ج","س"],weekHeader:"أسبوع",dateFormat:"dd/mm/yy",firstDay:6,isRTL:!0,showMonthAfterYear:!1,yearSuffix:""}),n.locale("ar-dz",{buttonText:{month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},allDayText:"اليوم كله",eventLimitText:"أخرى",noEventsMessage:"أي أحداث لعرض"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("ar-dz",{months:"جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),monthsShort:"جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"احد_اثنين_ثلاثاء_اربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"أح_إث_ثلا_أر_خم_جم_سب".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",ss:"%d ثانية",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},week:{dow:0,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(76);var n=t(1);n.datepickerLocale("ar-kw","ar",{closeText:"إغلاق",prevText:"<السابق",nextText:"التالي>",currentText:"اليوم",monthNames:["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],monthNamesShort:["1","2","3","4","5","6","7","8","9","10","11","12"],dayNames:["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت"],dayNamesShort:["أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت"],dayNamesMin:["ح","ن","ث","ر","خ","ج","س"],weekHeader:"أسبوع",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!0,showMonthAfterYear:!1,yearSuffix:""}),n.locale("ar-kw",{buttonText:{month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},allDayText:"اليوم كله",eventLimitText:"أخرى",noEventsMessage:"أي أحداث لعرض"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("ar-kw",{months:"يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),monthsShort:"يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),weekdays:"الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",ss:"%d ثانية",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},week:{dow:0,doy:12}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(78);var n=t(1);n.datepickerLocale("ar-ly","ar",{closeText:"إغلاق",prevText:"<السابق",nextText:"التالي>",currentText:"اليوم",monthNames:["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],monthNamesShort:["1","2","3","4","5","6","7","8","9","10","11","12"],dayNames:["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت"],dayNamesShort:["أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت"],dayNamesMin:["ح","ن","ث","ر","خ","ج","س"],weekHeader:"أسبوع",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!0,showMonthAfterYear:!1,yearSuffix:""}),n.locale("ar-ly",{buttonText:{month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},allDayText:"اليوم كله",eventLimitText:"أخرى",noEventsMessage:"أي أحداث لعرض"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){var a={1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",0:"0"},t=function(e){return 0===e?0:1===e?1:2===e?2:e%100>=3&&e%100<=10?3:e%100>=11?4:5},n={s:["أقل من ثانية","ثانية واحدة",["ثانيتان","ثانيتين"],"%d ثوان","%d ثانية","%d ثانية"],m:["أقل من دقيقة","دقيقة واحدة",["دقيقتان","دقيقتين"],"%d دقائق","%d دقيقة","%d دقيقة"],h:["أقل من ساعة","ساعة واحدة",["ساعتان","ساعتين"],"%d ساعات","%d ساعة","%d ساعة"],d:["أقل من يوم","يوم واحد",["يومان","يومين"],"%d أيام","%d يومًا","%d يوم"],M:["أقل من شهر","شهر واحد",["شهران","شهرين"],"%d أشهر","%d شهرا","%d شهر"],y:["أقل من عام","عام واحد",["عامان","عامين"],"%d أعوام","%d عامًا","%d عام"]},r=function(e){return function(a,r,s,d){var i=t(a),o=n[e][t(a)];return 2===i&&(o=o[r?0:1]),o.replace(/%d/i,a)}},s=["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"];return e.defineLocale("ar-ly",{months:s,monthsShort:s,weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"D/‏M/‏YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/ص|م/,isPM:function(e){return"م"===e},meridiem:function(e,a,t){return e<12?"ص":"م"},calendar:{sameDay:"[اليوم عند الساعة] LT",nextDay:"[غدًا عند الساعة] LT",nextWeek:"dddd [عند الساعة] LT",lastDay:"[أمس عند الساعة] LT",lastWeek:"dddd [عند الساعة] LT",sameElse:"L"},relativeTime:{future:"بعد %s",past:"منذ %s",s:r("s"),ss:r("s"),m:r("m"),mm:r("m"),h:r("h"),hh:r("h"),d:r("d"),dd:r("d"),M:r("M"),MM:r("M"),y:r("y"),yy:r("y")},preparse:function(e){return e.replace(/،/g,",")},postformat:function(e){return e.replace(/\d/g,function(e){return a[e]}).replace(/,/g,"،")},week:{dow:6,doy:12}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(80);var n=t(1);n.datepickerLocale("ar-ma","ar",{closeText:"إغلاق",prevText:"<السابق",nextText:"التالي>",currentText:"اليوم",monthNames:["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],monthNamesShort:["1","2","3","4","5","6","7","8","9","10","11","12"],dayNames:["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت"],dayNamesShort:["أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت"],dayNamesMin:["ح","ن","ث","ر","خ","ج","س"],weekHeader:"أسبوع",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!0,showMonthAfterYear:!1,yearSuffix:""}),n.locale("ar-ma",{buttonText:{month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},allDayText:"اليوم كله",eventLimitText:"أخرى",noEventsMessage:"أي أحداث لعرض"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("ar-ma",{months:"يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),monthsShort:"يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),weekdays:"الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",ss:"%d ثانية",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},week:{dow:6,doy:12}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(82);var n=t(1);n.datepickerLocale("ar-sa","ar",{closeText:"إغلاق",prevText:"<السابق",nextText:"التالي>",currentText:"اليوم",monthNames:["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],monthNamesShort:["1","2","3","4","5","6","7","8","9","10","11","12"],dayNames:["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت"],dayNamesShort:["أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت"],dayNamesMin:["ح","ن","ث","ر","خ","ج","س"],weekHeader:"أسبوع",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!0,showMonthAfterYear:!1,yearSuffix:""}),n.locale("ar-sa",{buttonText:{month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},allDayText:"اليوم كله",eventLimitText:"أخرى",noEventsMessage:"أي أحداث لعرض"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){var a={1:"١",2:"٢",3:"٣",4:"٤",5:"٥",6:"٦",7:"٧",8:"٨",9:"٩",0:"٠"},t={"١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9","٠":"0"};return e.defineLocale("ar-sa",{months:"يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),monthsShort:"يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/ص|م/,isPM:function(e){return"م"===e},meridiem:function(e,a,t){return e<12?"ص":"م"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",ss:"%d ثانية",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},preparse:function(e){return e.replace(/[١٢٣٤٥٦٧٨٩٠]/g,function(e){return t[e]}).replace(/،/g,",")},postformat:function(e){return e.replace(/\d/g,function(e){return a[e]}).replace(/,/g,"،")},week:{dow:0,doy:6}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(84);var n=t(1);n.datepickerLocale("ar-tn","ar",{closeText:"إغلاق",prevText:"<السابق",nextText:"التالي>",currentText:"اليوم",monthNames:["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],monthNamesShort:["1","2","3","4","5","6","7","8","9","10","11","12"],dayNames:["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت"],dayNamesShort:["أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت"],dayNamesMin:["ح","ن","ث","ر","خ","ج","س"],weekHeader:"أسبوع",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!0,showMonthAfterYear:!1,yearSuffix:""}),n.locale("ar-tn",{buttonText:{month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},allDayText:"اليوم كله",eventLimitText:"أخرى",noEventsMessage:"أي أحداث لعرض"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("ar-tn",{months:"جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),monthsShort:"جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر".split("_"),weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",ss:"%d ثانية",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(86);var n=t(1);n.datepickerLocale("ar","ar",{closeText:"إغلاق",prevText:"<السابق",nextText:"التالي>",currentText:"اليوم",monthNames:["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],monthNamesShort:["1","2","3","4","5","6","7","8","9","10","11","12"],dayNames:["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت"],dayNamesShort:["أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت"],dayNamesMin:["ح","ن","ث","ر","خ","ج","س"],weekHeader:"أسبوع",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!0,showMonthAfterYear:!1,yearSuffix:""}),n.locale("ar",{buttonText:{month:"شهر",week:"أسبوع",day:"يوم",list:"أجندة"},allDayText:"اليوم كله",eventLimitText:"أخرى",noEventsMessage:"أي أحداث لعرض"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){var a={1:"١",2:"٢",3:"٣",4:"٤",5:"٥",6:"٦",7:"٧",8:"٨",9:"٩",0:"٠"},t={"١":"1","٢":"2","٣":"3","٤":"4","٥":"5","٦":"6","٧":"7","٨":"8","٩":"9","٠":"0"},n=function(e){return 0===e?0:1===e?1:2===e?2:e%100>=3&&e%100<=10?3:e%100>=11?4:5},r={s:["أقل من ثانية","ثانية واحدة",["ثانيتان","ثانيتين"],"%d ثوان","%d ثانية","%d ثانية"],m:["أقل من دقيقة","دقيقة واحدة",["دقيقتان","دقيقتين"],"%d دقائق","%d دقيقة","%d دقيقة"],h:["أقل من ساعة","ساعة واحدة",["ساعتان","ساعتين"],"%d ساعات","%d ساعة","%d ساعة"],d:["أقل من يوم","يوم واحد",["يومان","يومين"],"%d أيام","%d يومًا","%d يوم"],M:["أقل من شهر","شهر واحد",["شهران","شهرين"],"%d أشهر","%d شهرا","%d شهر"],y:["أقل من عام","عام واحد",["عامان","عامين"],"%d أعوام","%d عامًا","%d عام"]},s=function(e){return function(a,t,s,d){var i=n(a),o=r[e][n(a)];return 2===i&&(o=o[t?0:1]),o.replace(/%d/i,a)}},d=["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"];return e.defineLocale("ar",{months:d,monthsShort:d,weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"D/‏M/‏YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},meridiemParse:/ص|م/,isPM:function(e){return"م"===e},meridiem:function(e,a,t){return e<12?"ص":"م"},calendar:{sameDay:"[اليوم عند الساعة] LT",nextDay:"[غدًا عند الساعة] LT",nextWeek:"dddd [عند الساعة] LT",lastDay:"[أمس عند الساعة] LT",lastWeek:"dddd [عند الساعة] LT",sameElse:"L"},relativeTime:{future:"بعد %s",past:"منذ %s",s:s("s"),ss:s("s"),m:s("m"),mm:s("m"),h:s("h"),hh:s("h"),d:s("d"),dd:s("d"),M:s("M"),MM:s("M"),y:s("y"),yy:s("y")},preparse:function(e){return e.replace(/[١٢٣٤٥٦٧٨٩٠]/g,function(e){return t[e]}).replace(/،/g,",")},postformat:function(e){return e.replace(/\d/g,function(e){return a[e]}).replace(/,/g,"،")},week:{dow:6,doy:12}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(88);var n=t(1);n.datepickerLocale("be","be",{closeText:"Зачыніць",prevText:"<Папярэд",nextText:"След>",currentText:"Сёння",monthNames:["Студзень","Люты","Сакавік","Красавік","Трав","Чэрвень","Ліпень","Жнівень","Верасень","Кастрычнік","Лістапад","Снежань"],monthNamesShort:["Студ","Лют","Сак","Крас","Трав","Чэрв","Ліп","Жнів","Вер","Каст","Ліст","Снеж"],dayNames:["нядзеля","панядзелак","аўторак","серада","чацвер","пятніца","субота"],dayNamesShort:["ндз","пнд","аўт","срд","чцв","птн","сбт"],dayNamesMin:["Нд","Пн","Ат","Ср","Чц","Пт","Сб"],weekHeader:"Ндз",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("be",{buttonText:{month:"Месяц",week:"Тыдзень",day:"Дзень",list:"Парадак дня"},allDayHtml:"Увесь
дзень",eventLimitText:function(e){return"+ яшчэ "+e},noEventsMessage:"Няма падзей для адлюстравання"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){function a(e,a){var t=e.split("_");return a%10==1&&a%100!=11?t[0]:a%10>=2&&a%10<=4&&(a%100<10||a%100>=20)?t[1]:t[2]}function t(e,t,n){var r={ss:t?"секунда_секунды_секунд":"секунду_секунды_секунд",mm:t?"хвіліна_хвіліны_хвілін":"хвіліну_хвіліны_хвілін",hh:t?"гадзіна_гадзіны_гадзін":"гадзіну_гадзіны_гадзін",dd:"дзень_дні_дзён",MM:"месяц_месяцы_месяцаў",yy:"год_гады_гадоў"};return"m"===n?t?"хвіліна":"хвіліну":"h"===n?t?"гадзіна":"гадзіну":e+" "+a(r[n],+e)}return e.defineLocale("be",{months:{format:"студзеня_лютага_сакавіка_красавіка_траўня_чэрвеня_ліпеня_жніўня_верасня_кастрычніка_лістапада_снежня".split("_"),standalone:"студзень_люты_сакавік_красавік_травень_чэрвень_ліпень_жнівень_верасень_кастрычнік_лістапад_снежань".split("_")},monthsShort:"студ_лют_сак_крас_трав_чэрв_ліп_жнів_вер_каст_ліст_снеж".split("_"),weekdays:{format:"нядзелю_панядзелак_аўторак_сераду_чацвер_пятніцу_суботу".split("_"),standalone:"нядзеля_панядзелак_аўторак_серада_чацвер_пятніца_субота".split("_"),isFormat:/\[ ?[Ууў] ?(?:мінулую|наступную)? ?\] ?dddd/},weekdaysShort:"нд_пн_ат_ср_чц_пт_сб".split("_"),weekdaysMin:"нд_пн_ат_ср_чц_пт_сб".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY г.",LLL:"D MMMM YYYY г., HH:mm",LLLL:"dddd, D MMMM YYYY г., HH:mm"},calendar:{sameDay:"[Сёння ў] LT",nextDay:"[Заўтра ў] LT",lastDay:"[Учора ў] LT",nextWeek:function(){return"[У] dddd [ў] LT"},lastWeek:function(){switch(this.day()){case 0:case 3:case 5:case 6:return"[У мінулую] dddd [ў] LT";case 1:case 2:case 4:return"[У мінулы] dddd [ў] LT"}},sameElse:"L"},relativeTime:{future:"праз %s",past:"%s таму",s:"некалькі секунд",m:t,mm:t,h:t,hh:t,d:"дзень",dd:t,M:"месяц",MM:t,y:"год",yy:t},meridiemParse:/ночы|раніцы|дня|вечара/,isPM:function(e){return/^(дня|вечара)$/.test(e)},meridiem:function(e,a,t){return e<4?"ночы":e<12?"раніцы":e<17?"дня":"вечара"},dayOfMonthOrdinalParse:/\d{1,2}-(і|ы|га)/,ordinal:function(e,a){switch(a){case"M":case"d":case"DDD":case"w":case"W":return e%10!=2&&e%10!=3||e%100==12||e%100==13?e+"-ы":e+"-і";case"D":return e+"-га";default:return e}},week:{dow:1,doy:7}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(90);var n=t(1);n.datepickerLocale("bg","bg",{closeText:"затвори",prevText:"<назад",nextText:"напред>",nextBigText:">>",currentText:"днес",monthNames:["Януари","Февруари","Март","Април","Май","Юни","Юли","Август","Септември","Октомври","Ноември","Декември"],monthNamesShort:["Яну","Фев","Мар","Апр","Май","Юни","Юли","Авг","Сеп","Окт","Нов","Дек"],dayNames:["Неделя","Понеделник","Вторник","Сряда","Четвъртък","Петък","Събота"],dayNamesShort:["Нед","Пон","Вто","Сря","Чет","Пет","Съб"],dayNamesMin:["Не","По","Вт","Ср","Че","Пе","Съ"],weekHeader:"Wk",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("bg",{buttonText:{month:"Месец",week:"Седмица",day:"Ден",list:"График"},allDayText:"Цял ден",eventLimitText:function(e){return"+още "+e},noEventsMessage:"Няма събития за показване"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("bg",{months:"януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември".split("_"),monthsShort:"янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек".split("_"),weekdays:"неделя_понеделник_вторник_сряда_четвъртък_петък_събота".split("_"),weekdaysShort:"нед_пон_вто_сря_чет_пет_съб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"D.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[Днес в] LT",nextDay:"[Утре в] LT",nextWeek:"dddd [в] LT",lastDay:"[Вчера в] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[В изминалата] dddd [в] LT";case 1:case 2:case 4:case 5:return"[В изминалия] dddd [в] LT"}},sameElse:"L"},relativeTime:{future:"след %s",past:"преди %s",s:"няколко секунди",ss:"%d секунди",m:"минута",mm:"%d минути",h:"час",hh:"%d часа",d:"ден",dd:"%d дни",M:"месец",MM:"%d месеца",y:"година",yy:"%d години"},dayOfMonthOrdinalParse:/\d{1,2}-(ев|ен|ти|ви|ри|ми)/,ordinal:function(e){var a=e%10,t=e%100;return 0===e?e+"-ев":0===t?e+"-ен":t>10&&t<20?e+"-ти":1===a?e+"-ви":2===a?e+"-ри":7===a||8===a?e+"-ми":e+"-ти"},week:{dow:1,doy:7}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(92);var n=t(1);n.datepickerLocale("bs","bs",{closeText:"Zatvori",prevText:"<",nextText:">",currentText:"Danas",monthNames:["Januar","Februar","Mart","April","Maj","Juni","Juli","August","Septembar","Oktobar","Novmbar","Decembar"],monthNamesShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],dayNames:["Nedjelja","Ponedjeljak","Utorak","Srijeda","Četvrtak","Petak","Subota"],dayNamesShort:["Ned","Pon","Uto","Sri","Čet","Pet","Sub"],dayNamesMin:["Ne","Po","Ut","Sr","Če","Pe","Su"],weekHeader:"Sed",dateFormat:"dd.mm.yy.",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("bs",{buttonText:{prev:"Prošli",next:"Sljedeći",month:"Mjesec",week:"Sedmica",day:"Dan",list:"Raspored"},allDayText:"Cijeli dan",eventLimitText:function(e){return"+ još "+e},noEventsMessage:"Nema događaja za prikazivanje"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){function a(e,a,t){var n=e+" ";switch(t){case"ss":return n+=1===e?"sekunda":2===e||3===e||4===e?"sekunde":"sekundi";case"m":return a?"jedna minuta":"jedne minute";case"mm":return n+=1===e?"minuta":2===e||3===e||4===e?"minute":"minuta";case"h":return a?"jedan sat":"jednog sata";case"hh":return n+=1===e?"sat":2===e||3===e||4===e?"sata":"sati";case"dd":return n+=1===e?"dan":"dana";case"MM":return n+=1===e?"mjesec":2===e||3===e||4===e?"mjeseca":"mjeseci";case"yy":return n+=1===e?"godina":2===e||3===e||4===e?"godine":"godina"}}return e.defineLocale("bs",{months:"januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[jučer u] LT",lastWeek:function(){switch(this.day()){case 0:case 3:return"[prošlu] dddd [u] LT";case 6:return"[prošle] [subote] [u] LT";case 1:case 2:case 4:case 5:return"[prošli] dddd [u] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"par sekundi",ss:a,m:a,mm:a,h:a,hh:a,d:"dan",dd:a,M:"mjesec",MM:a,y:"godinu",yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(94);var n=t(1);n.datepickerLocale("ca","ca",{closeText:"Tanca",prevText:"Anterior",nextText:"Següent",currentText:"Avui",monthNames:["gener","febrer","març","abril","maig","juny","juliol","agost","setembre","octubre","novembre","desembre"],monthNamesShort:["gen","feb","març","abr","maig","juny","jul","ag","set","oct","nov","des"],dayNames:["diumenge","dilluns","dimarts","dimecres","dijous","divendres","dissabte"],dayNamesShort:["dg","dl","dt","dc","dj","dv","ds"],dayNamesMin:["dg","dl","dt","dc","dj","dv","ds"],weekHeader:"Set",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("ca",{buttonText:{month:"Mes",week:"Setmana",day:"Dia",list:"Agenda"},allDayText:"Tot el dia",eventLimitText:"més",noEventsMessage:"No hi ha esdeveniments per mostrar"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("ca",{months:{standalone:"gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre".split("_"),format:"de gener_de febrer_de març_d'abril_de maig_de juny_de juliol_d'agost_de setembre_d'octubre_de novembre_de desembre".split("_"),isFormat:/D[oD]?(\s)+MMMM/},monthsShort:"gen._febr._març_abr._maig_juny_jul._ag._set._oct._nov._des.".split("_"),monthsParseExact:!0,weekdays:"diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte".split("_"),weekdaysShort:"dg._dl._dt._dc._dj._dv._ds.".split("_"),weekdaysMin:"dg_dl_dt_dc_dj_dv_ds".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM [de] YYYY",ll:"D MMM YYYY",LLL:"D MMMM [de] YYYY [a les] H:mm",lll:"D MMM YYYY, H:mm",LLLL:"dddd D MMMM [de] YYYY [a les] H:mm",llll:"ddd D MMM YYYY, H:mm"},calendar:{sameDay:function(){return"[avui a "+(1!==this.hours()?"les":"la")+"] LT"},nextDay:function(){return"[demà a "+(1!==this.hours()?"les":"la")+"] LT"},nextWeek:function(){return"dddd [a "+(1!==this.hours()?"les":"la")+"] LT"},lastDay:function(){return"[ahir a "+(1!==this.hours()?"les":"la")+"] LT"},lastWeek:function(){return"[el] dddd [passat a "+(1!==this.hours()?"les":"la")+"] LT"},sameElse:"L"},relativeTime:{future:"d'aquí %s",past:"fa %s",s:"uns segons",ss:"%d segons",m:"un minut",mm:"%d minuts",h:"una hora",hh:"%d hores",d:"un dia",dd:"%d dies",M:"un mes",MM:"%d mesos",y:"un any",yy:"%d anys"},dayOfMonthOrdinalParse:/\d{1,2}(r|n|t|è|a)/,ordinal:function(e,a){var t=1===e?"r":2===e?"n":3===e?"r":4===e?"t":"è";return"w"!==a&&"W"!==a||(t="a"),e+t},week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(96);var n=t(1);n.datepickerLocale("cs","cs",{closeText:"Zavřít",prevText:"<Dříve",nextText:"Později>",currentText:"Nyní",monthNames:["leden","únor","březen","duben","květen","červen","červenec","srpen","září","říjen","listopad","prosinec"],monthNamesShort:["led","úno","bře","dub","kvě","čer","čvc","srp","zář","říj","lis","pro"],dayNames:["neděle","pondělí","úterý","středa","čtvrtek","pátek","sobota"],dayNamesShort:["ne","po","út","st","čt","pá","so"],dayNamesMin:["ne","po","út","st","čt","pá","so"],weekHeader:"Týd",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("cs",{buttonText:{month:"Měsíc",week:"Týden",day:"Den",list:"Agenda"},allDayText:"Celý den",eventLimitText:function(e){return"+další: "+e},noEventsMessage:"Žádné akce k zobrazení"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){function a(e){return e>1&&e<5&&1!=~~(e/10)}function t(e,t,n,r){var s=e+" ";switch(n){case"s":return t||r?"pár sekund":"pár sekundami";case"ss":return t||r?s+(a(e)?"sekundy":"sekund"):s+"sekundami";case"m":return t?"minuta":r?"minutu":"minutou";case"mm":return t||r?s+(a(e)?"minuty":"minut"):s+"minutami";case"h":return t?"hodina":r?"hodinu":"hodinou";case"hh":return t||r?s+(a(e)?"hodiny":"hodin"):s+"hodinami";case"d":return t||r?"den":"dnem";case"dd":return t||r?s+(a(e)?"dny":"dní"):s+"dny";case"M":return t||r?"měsíc":"měsícem";case"MM":return t||r?s+(a(e)?"měsíce":"měsíců"):s+"měsíci";case"y":return t||r?"rok":"rokem";case"yy":return t||r?s+(a(e)?"roky":"let"):s+"lety"}}var n="leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec".split("_"),r="led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro".split("_"),s=[/^led/i,/^úno/i,/^bře/i,/^dub/i,/^kvě/i,/^(čvn|červen$|června)/i,/^(čvc|červenec|července)/i,/^srp/i,/^zář/i,/^říj/i,/^lis/i,/^pro/i],d=/^(leden|únor|březen|duben|květen|červenec|července|červen|června|srpen|září|říjen|listopad|prosinec|led|úno|bře|dub|kvě|čvn|čvc|srp|zář|říj|lis|pro)/i;return e.defineLocale("cs",{months:n,monthsShort:r,monthsRegex:d,monthsShortRegex:d,monthsStrictRegex:/^(leden|ledna|února|únor|březen|března|duben|dubna|květen|května|červenec|července|červen|června|srpen|srpna|září|říjen|října|listopadu|listopad|prosinec|prosince)/i,monthsShortStrictRegex:/^(led|úno|bře|dub|kvě|čvn|čvc|srp|zář|říj|lis|pro)/i,monthsParse:s,longMonthsParse:s,shortMonthsParse:s,weekdays:"neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota".split("_"),weekdaysShort:"ne_po_út_st_čt_pá_so".split("_"),weekdaysMin:"ne_po_út_st_čt_pá_so".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd D. MMMM YYYY H:mm",l:"D. M. YYYY"},calendar:{sameDay:"[dnes v] LT",nextDay:"[zítra v] LT",nextWeek:function(){switch(this.day()){case 0:return"[v neděli v] LT";case 1:case 2:return"[v] dddd [v] LT";case 3:return"[ve středu v] LT";case 4:return"[ve čtvrtek v] LT";case 5:return"[v pátek v] LT";case 6:return"[v sobotu v] LT"}},lastDay:"[včera v] LT",lastWeek:function(){switch(this.day()){case 0:return"[minulou neděli v] LT";case 1:case 2:return"[minulé] dddd [v] LT";case 3:return"[minulou středu v] LT";case 4:case 5:return"[minulý] dddd [v] LT";case 6:return"[minulou sobotu v] LT"}},sameElse:"L"}, +relativeTime:{future:"za %s",past:"před %s",s:t,ss:t,m:t,mm:t,h:t,hh:t,d:t,dd:t,M:t,MM:t,y:t,yy:t},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(98);var n=t(1);n.datepickerLocale("da","da",{closeText:"Luk",prevText:"<Forrige",nextText:"Næste>",currentText:"Idag",monthNames:["Januar","Februar","Marts","April","Maj","Juni","Juli","August","September","Oktober","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],dayNames:["Søndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lørdag"],dayNamesShort:["Søn","Man","Tir","Ons","Tor","Fre","Lør"],dayNamesMin:["Sø","Ma","Ti","On","To","Fr","Lø"],weekHeader:"Uge",dateFormat:"dd-mm-yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("da",{buttonText:{month:"Måned",week:"Uge",day:"Dag",list:"Agenda"},allDayText:"Hele dagen",eventLimitText:"flere",noEventsMessage:"Ingen arrangementer at vise"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("da",{months:"januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"søn_man_tir_ons_tor_fre_lør".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd [d.] D. MMMM YYYY [kl.] HH:mm"},calendar:{sameDay:"[i dag kl.] LT",nextDay:"[i morgen kl.] LT",nextWeek:"på dddd [kl.] LT",lastDay:"[i går kl.] LT",lastWeek:"[i] dddd[s kl.] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"få sekunder",ss:"%d sekunder",m:"et minut",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dage",M:"en måned",MM:"%d måneder",y:"et år",yy:"%d år"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(100);var n=t(1);n.datepickerLocale("de-at","de",{closeText:"Schließen",prevText:"<Zurück",nextText:"Vor>",currentText:"Heute",monthNames:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],monthNamesShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],dayNames:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],dayNamesShort:["So","Mo","Di","Mi","Do","Fr","Sa"],dayNamesMin:["So","Mo","Di","Mi","Do","Fr","Sa"],weekHeader:"KW",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("de-at",{buttonText:{year:"Jahr",month:"Monat",week:"Woche",day:"Tag",list:"Terminübersicht"},allDayText:"Ganztägig",eventLimitText:function(e){return"+ weitere "+e},noEventsMessage:"Keine Ereignisse anzuzeigen"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){function a(e,a,t,n){var r={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[e+" Tage",e+" Tagen"],M:["ein Monat","einem Monat"],MM:[e+" Monate",e+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[e+" Jahre",e+" Jahren"]};return a?r[t][0]:r[t][1]}return e.defineLocale("de-at",{months:"Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jän._Feb._März_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd, D. MMMM YYYY HH:mm"},calendar:{sameDay:"[heute um] LT [Uhr]",sameElse:"L",nextDay:"[morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",ss:"%d Sekunden",m:a,mm:"%d Minuten",h:a,hh:"%d Stunden",d:a,dd:a,M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(102);var n=t(1);n.datepickerLocale("de-ch","de",{closeText:"Schließen",prevText:"<Zurück",nextText:"Vor>",currentText:"Heute",monthNames:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],monthNamesShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],dayNames:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],dayNamesShort:["So","Mo","Di","Mi","Do","Fr","Sa"],dayNamesMin:["So","Mo","Di","Mi","Do","Fr","Sa"],weekHeader:"KW",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("de-ch",{buttonText:{year:"Jahr",month:"Monat",week:"Woche",day:"Tag",list:"Terminübersicht"},allDayText:"Ganztägig",eventLimitText:function(e){return"+ weitere "+e},noEventsMessage:"Keine Ereignisse anzuzeigen"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){function a(e,a,t,n){var r={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[e+" Tage",e+" Tagen"],M:["ein Monat","einem Monat"],MM:[e+" Monate",e+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[e+" Jahre",e+" Jahren"]};return a?r[t][0]:r[t][1]}return e.defineLocale("de-ch",{months:"Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Feb._März_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd, D. MMMM YYYY HH:mm"},calendar:{sameDay:"[heute um] LT [Uhr]",sameElse:"L",nextDay:"[morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",ss:"%d Sekunden",m:a,mm:"%d Minuten",h:a,hh:"%d Stunden",d:a,dd:a,M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(104);var n=t(1);n.datepickerLocale("de","de",{closeText:"Schließen",prevText:"<Zurück",nextText:"Vor>",currentText:"Heute",monthNames:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],monthNamesShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],dayNames:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],dayNamesShort:["So","Mo","Di","Mi","Do","Fr","Sa"],dayNamesMin:["So","Mo","Di","Mi","Do","Fr","Sa"],weekHeader:"KW",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("de",{buttonText:{year:"Jahr",month:"Monat",week:"Woche",day:"Tag",list:"Terminübersicht"},allDayText:"Ganztägig",eventLimitText:function(e){return"+ weitere "+e},noEventsMessage:"Keine Ereignisse anzuzeigen",dayOfMonthFormat:"ddd DD.MM."})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){function a(e,a,t,n){var r={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[e+" Tage",e+" Tagen"],M:["ein Monat","einem Monat"],MM:[e+" Monate",e+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[e+" Jahre",e+" Jahren"]};return a?r[t][0]:r[t][1]}return e.defineLocale("de",{months:"Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Feb._März_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY HH:mm",LLLL:"dddd, D. MMMM YYYY HH:mm"},calendar:{sameDay:"[heute um] LT [Uhr]",sameElse:"L",nextDay:"[morgen um] LT [Uhr]",nextWeek:"dddd [um] LT [Uhr]",lastDay:"[gestern um] LT [Uhr]",lastWeek:"[letzten] dddd [um] LT [Uhr]"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",ss:"%d Sekunden",m:a,mm:"%d Minuten",h:a,hh:"%d Stunden",d:a,dd:a,M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(106);var n=t(1);n.datepickerLocale("el","el",{closeText:"Κλείσιμο",prevText:"Προηγούμενος",nextText:"Επόμενος",currentText:"Σήμερα",monthNames:["Ιανουάριος","Φεβρουάριος","Μάρτιος","Απρίλιος","Μάιος","Ιούνιος","Ιούλιος","Αύγουστος","Σεπτέμβριος","Οκτώβριος","Νοέμβριος","Δεκέμβριος"],monthNamesShort:["Ιαν","Φεβ","Μαρ","Απρ","Μαι","Ιουν","Ιουλ","Αυγ","Σεπ","Οκτ","Νοε","Δεκ"],dayNames:["Κυριακή","Δευτέρα","Τρίτη","Τετάρτη","Πέμπτη","Παρασκευή","Σάββατο"],dayNamesShort:["Κυρ","Δευ","Τρι","Τετ","Πεμ","Παρ","Σαβ"],dayNamesMin:["Κυ","Δε","Τρ","Τε","Πε","Πα","Σα"],weekHeader:"Εβδ",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("el",{buttonText:{month:"Μήνας",week:"Εβδομάδα",day:"Ημέρα",list:"Ατζέντα"},allDayText:"Ολοήμερο",eventLimitText:"περισσότερα",noEventsMessage:"Δεν υπάρχουν γεγονότα για να εμφανιστεί"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){function a(e){return e instanceof Function||"[object Function]"===Object.prototype.toString.call(e)}return e.defineLocale("el",{monthsNominativeEl:"Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος".split("_"),monthsGenitiveEl:"Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου".split("_"),months:function(e,a){return e?"string"==typeof a&&/D/.test(a.substring(0,a.indexOf("MMMM")))?this._monthsGenitiveEl[e.month()]:this._monthsNominativeEl[e.month()]:this._monthsNominativeEl},monthsShort:"Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ".split("_"),weekdays:"Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο".split("_"),weekdaysShort:"Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ".split("_"),weekdaysMin:"Κυ_Δε_Τρ_Τε_Πε_Πα_Σα".split("_"),meridiem:function(e,a,t){return e>11?t?"μμ":"ΜΜ":t?"πμ":"ΠΜ"},isPM:function(e){return"μ"===(e+"").toLowerCase()[0]},meridiemParse:/[ΠΜ]\.?Μ?\.?/i,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendarEl:{sameDay:"[Σήμερα {}] LT",nextDay:"[Αύριο {}] LT",nextWeek:"dddd [{}] LT",lastDay:"[Χθες {}] LT",lastWeek:function(){switch(this.day()){case 6:return"[το προηγούμενο] dddd [{}] LT";default:return"[την προηγούμενη] dddd [{}] LT"}},sameElse:"L"},calendar:function(e,t){var n=this._calendarEl[e],r=t&&t.hours();return a(n)&&(n=n.apply(t)),n.replace("{}",r%12==1?"στη":"στις")},relativeTime:{future:"σε %s",past:"%s πριν",s:"λίγα δευτερόλεπτα",ss:"%d δευτερόλεπτα",m:"ένα λεπτό",mm:"%d λεπτά",h:"μία ώρα",hh:"%d ώρες",d:"μία μέρα",dd:"%d μέρες",M:"ένας μήνας",MM:"%d μήνες",y:"ένας χρόνος",yy:"%d χρόνια"},dayOfMonthOrdinalParse:/\d{1,2}η/,ordinal:"%dη",week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(108);var n=t(1);n.datepickerLocale("en-au","en-AU",{closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("en-au")},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("en-au",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")},week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(110),t(1).locale("en-ca")},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("en-ca",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"YYYY-MM-DD",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(112);var n=t(1);n.datepickerLocale("en-gb","en-GB",{closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("en-gb")},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("en-gb",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")},week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(114),t(1).locale("en-ie")},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("en-ie",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")},week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(116);var n=t(1);n.datepickerLocale("en-nz","en-NZ",{closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("en-nz")},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("en-nz",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY h:mm A",LLLL:"dddd, D MMMM YYYY h:mm A"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},dayOfMonthOrdinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th")},week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(118);var n=t(1);n.datepickerLocale("es-do","es",{closeText:"Cerrar",prevText:"<Ant",nextText:"Sig>",currentText:"Hoy",monthNames:["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],monthNamesShort:["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],dayNames:["domingo","lunes","martes","miércoles","jueves","viernes","sábado"],dayNamesShort:["dom","lun","mar","mié","jue","vie","sáb"],dayNamesMin:["D","L","M","X","J","V","S"],weekHeader:"Sm",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("es-do",{buttonText:{month:"Mes",week:"Semana",day:"Día",list:"Agenda"},allDayHtml:"Todo
el día",eventLimitText:"más",noEventsMessage:"No hay eventos para mostrar"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){var a="ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),t="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),n=[/^ene/i,/^feb/i,/^mar/i,/^abr/i,/^may/i,/^jun/i,/^jul/i,/^ago/i,/^sep/i,/^oct/i,/^nov/i,/^dic/i],r=/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i;return e.defineLocale("es-do",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(e,n){return e?/-MMM-/.test(n)?t[e.month()]:a[e.month()]:a},monthsRegex:r,monthsShortRegex:r,monthsStrictRegex:/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,monthsShortStrictRegex:/^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,monthsParse:n,longMonthsParse:n,shortMonthsParse:n,weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY h:mm A",LLLL:"dddd, D [de] MMMM [de] YYYY h:mm A"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(120);var n=t(1);n.datepickerLocale("es-us","es",{closeText:"Cerrar",prevText:"<Ant",nextText:"Sig>",currentText:"Hoy",monthNames:["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],monthNamesShort:["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],dayNames:["domingo","lunes","martes","miércoles","jueves","viernes","sábado"],dayNamesShort:["dom","lun","mar","mié","jue","vie","sáb"],dayNamesMin:["D","L","M","X","J","V","S"],weekHeader:"Sm",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("es-us",{buttonText:{month:"Mes",week:"Semana",day:"Día",list:"Agenda"},allDayHtml:"Todo
el día",eventLimitText:"más",noEventsMessage:"No hay eventos para mostrar"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){var a="ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),t="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),n=[/^ene/i,/^feb/i,/^mar/i,/^abr/i,/^may/i,/^jun/i,/^jul/i,/^ago/i,/^sep/i,/^oct/i,/^nov/i,/^dic/i],r=/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i;return e.defineLocale("es-us",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(e,n){return e?/-MMM-/.test(n)?t[e.month()]:a[e.month()]:a},monthsRegex:r,monthsShortRegex:r,monthsStrictRegex:/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,monthsShortStrictRegex:/^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,monthsParse:n,longMonthsParse:n,shortMonthsParse:n,weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"h:mm A",LTS:"h:mm:ss A",L:"MM/DD/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY h:mm A",LLLL:"dddd, D [de] MMMM [de] YYYY h:mm A"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:0,doy:6}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(122);var n=t(1);n.datepickerLocale("es","es",{closeText:"Cerrar",prevText:"<Ant",nextText:"Sig>",currentText:"Hoy",monthNames:["enero","febrero","marzo","abril","mayo","junio","julio","agosto","septiembre","octubre","noviembre","diciembre"],monthNamesShort:["ene","feb","mar","abr","may","jun","jul","ago","sep","oct","nov","dic"],dayNames:["domingo","lunes","martes","miércoles","jueves","viernes","sábado"],dayNamesShort:["dom","lun","mar","mié","jue","vie","sáb"],dayNamesMin:["D","L","M","X","J","V","S"],weekHeader:"Sm",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("es",{buttonText:{month:"Mes",week:"Semana",day:"Día",list:"Agenda"},allDayHtml:"Todo
el día",eventLimitText:"más",noEventsMessage:"No hay eventos para mostrar"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){var a="ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),t="ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic".split("_"),n=[/^ene/i,/^feb/i,/^mar/i,/^abr/i,/^may/i,/^jun/i,/^jul/i,/^ago/i,/^sep/i,/^oct/i,/^nov/i,/^dic/i],r=/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i;return e.defineLocale("es",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:function(e,n){return e?/-MMM-/.test(n)?t[e.month()]:a[e.month()]:a},monthsRegex:r,monthsShortRegex:r,monthsStrictRegex:/^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,monthsShortStrictRegex:/^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,monthsParse:n,longMonthsParse:n,shortMonthsParse:n,weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"do_lu_ma_mi_ju_vi_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY H:mm",LLLL:"dddd, D [de] MMMM [de] YYYY H:mm"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(124);var n=t(1);n.datepickerLocale("et","et",{closeText:"Sulge",prevText:"Eelnev",nextText:"Järgnev",currentText:"Täna",monthNames:["Jaanuar","Veebruar","Märts","Aprill","Mai","Juuni","Juuli","August","September","Oktoober","November","Detsember"],monthNamesShort:["Jaan","Veebr","Märts","Apr","Mai","Juuni","Juuli","Aug","Sept","Okt","Nov","Dets"],dayNames:["Pühapäev","Esmaspäev","Teisipäev","Kolmapäev","Neljapäev","Reede","Laupäev"],dayNamesShort:["Pühap","Esmasp","Teisip","Kolmap","Neljap","Reede","Laup"],dayNamesMin:["P","E","T","K","N","R","L"],weekHeader:"näd",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("et",{buttonText:{month:"Kuu",week:"Nädal",day:"Päev",list:"Päevakord"},allDayText:"Kogu päev",eventLimitText:function(e){return"+ veel "+e},noEventsMessage:"Kuvamiseks puuduvad sündmused"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){function a(e,a,t,n){var r={s:["mõne sekundi","mõni sekund","paar sekundit"],ss:[e+"sekundi",e+"sekundit"],m:["ühe minuti","üks minut"],mm:[e+" minuti",e+" minutit"],h:["ühe tunni","tund aega","üks tund"],hh:[e+" tunni",e+" tundi"],d:["ühe päeva","üks päev"],M:["kuu aja","kuu aega","üks kuu"],MM:[e+" kuu",e+" kuud"],y:["ühe aasta","aasta","üks aasta"],yy:[e+" aasta",e+" aastat"]};return a?r[t][2]?r[t][2]:r[t][1]:n?r[t][0]:r[t][1]}return e.defineLocale("et",{months:"jaanuar_veebruar_märts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember".split("_"),monthsShort:"jaan_veebr_märts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets".split("_"),weekdays:"pühapäev_esmaspäev_teisipäev_kolmapäev_neljapäev_reede_laupäev".split("_"),weekdaysShort:"P_E_T_K_N_R_L".split("_"),weekdaysMin:"P_E_T_K_N_R_L".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[Täna,] LT",nextDay:"[Homme,] LT",nextWeek:"[Järgmine] dddd LT",lastDay:"[Eile,] LT",lastWeek:"[Eelmine] dddd LT",sameElse:"L"},relativeTime:{future:"%s pärast",past:"%s tagasi",s:a,ss:a,m:a,mm:a,h:a,hh:a,d:a,dd:"%d päeva",M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(126);var n=t(1);n.datepickerLocale("eu","eu",{closeText:"Egina",prevText:"<Aur",nextText:"Hur>",currentText:"Gaur",monthNames:["urtarrila","otsaila","martxoa","apirila","maiatza","ekaina","uztaila","abuztua","iraila","urria","azaroa","abendua"],monthNamesShort:["urt.","ots.","mar.","api.","mai.","eka.","uzt.","abu.","ira.","urr.","aza.","abe."],dayNames:["igandea","astelehena","asteartea","asteazkena","osteguna","ostirala","larunbata"],dayNamesShort:["ig.","al.","ar.","az.","og.","ol.","lr."],dayNamesMin:["ig","al","ar","az","og","ol","lr"],weekHeader:"As",dateFormat:"yy-mm-dd",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("eu",{buttonText:{month:"Hilabetea",week:"Astea",day:"Eguna",list:"Agenda"},allDayHtml:"Egun
osoa",eventLimitText:"gehiago",noEventsMessage:"Ez dago ekitaldirik erakusteko"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("eu",{months:"urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua".split("_"),monthsShort:"urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.".split("_"),monthsParseExact:!0,weekdays:"igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata".split("_"),weekdaysShort:"ig._al._ar._az._og._ol._lr.".split("_"),weekdaysMin:"ig_al_ar_az_og_ol_lr".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"YYYY[ko] MMMM[ren] D[a]", +LLL:"YYYY[ko] MMMM[ren] D[a] HH:mm",LLLL:"dddd, YYYY[ko] MMMM[ren] D[a] HH:mm",l:"YYYY-M-D",ll:"YYYY[ko] MMM D[a]",lll:"YYYY[ko] MMM D[a] HH:mm",llll:"ddd, YYYY[ko] MMM D[a] HH:mm"},calendar:{sameDay:"[gaur] LT[etan]",nextDay:"[bihar] LT[etan]",nextWeek:"dddd LT[etan]",lastDay:"[atzo] LT[etan]",lastWeek:"[aurreko] dddd LT[etan]",sameElse:"L"},relativeTime:{future:"%s barru",past:"duela %s",s:"segundo batzuk",ss:"%d segundo",m:"minutu bat",mm:"%d minutu",h:"ordu bat",hh:"%d ordu",d:"egun bat",dd:"%d egun",M:"hilabete bat",MM:"%d hilabete",y:"urte bat",yy:"%d urte"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(128);var n=t(1);n.datepickerLocale("fa","fa",{closeText:"بستن",prevText:"<قبلی",nextText:"بعدی>",currentText:"امروز",monthNames:["ژانویه","فوریه","مارس","آوریل","مه","ژوئن","ژوئیه","اوت","سپتامبر","اکتبر","نوامبر","دسامبر"],monthNamesShort:["1","2","3","4","5","6","7","8","9","10","11","12"],dayNames:["يکشنبه","دوشنبه","سه‌شنبه","چهارشنبه","پنجشنبه","جمعه","شنبه"],dayNamesShort:["ی","د","س","چ","پ","ج","ش"],dayNamesMin:["ی","د","س","چ","پ","ج","ش"],weekHeader:"هف",dateFormat:"yy/mm/dd",firstDay:6,isRTL:!0,showMonthAfterYear:!1,yearSuffix:""}),n.locale("fa",{buttonText:{month:"ماه",week:"هفته",day:"روز",list:"برنامه"},allDayText:"تمام روز",eventLimitText:function(e){return"بیش از "+e},noEventsMessage:"هیچ رویدادی به نمایش"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){var a={1:"۱",2:"۲",3:"۳",4:"۴",5:"۵",6:"۶",7:"۷",8:"۸",9:"۹",0:"۰"},t={"۱":"1","۲":"2","۳":"3","۴":"4","۵":"5","۶":"6","۷":"7","۸":"8","۹":"9","۰":"0"};return e.defineLocale("fa",{months:"ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر".split("_"),monthsShort:"ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر".split("_"),weekdays:"یک‌شنبه_دوشنبه_سه‌شنبه_چهارشنبه_پنج‌شنبه_جمعه_شنبه".split("_"),weekdaysShort:"یک‌شنبه_دوشنبه_سه‌شنبه_چهارشنبه_پنج‌شنبه_جمعه_شنبه".split("_"),weekdaysMin:"ی_د_س_چ_پ_ج_ش".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},meridiemParse:/قبل از ظهر|بعد از ظهر/,isPM:function(e){return/بعد از ظهر/.test(e)},meridiem:function(e,a,t){return e<12?"قبل از ظهر":"بعد از ظهر"},calendar:{sameDay:"[امروز ساعت] LT",nextDay:"[فردا ساعت] LT",nextWeek:"dddd [ساعت] LT",lastDay:"[دیروز ساعت] LT",lastWeek:"dddd [پیش] [ساعت] LT",sameElse:"L"},relativeTime:{future:"در %s",past:"%s پیش",s:"چند ثانیه",ss:"ثانیه d%",m:"یک دقیقه",mm:"%d دقیقه",h:"یک ساعت",hh:"%d ساعت",d:"یک روز",dd:"%d روز",M:"یک ماه",MM:"%d ماه",y:"یک سال",yy:"%d سال"},preparse:function(e){return e.replace(/[۰-۹]/g,function(e){return t[e]}).replace(/،/g,",")},postformat:function(e){return e.replace(/\d/g,function(e){return a[e]}).replace(/,/g,"،")},dayOfMonthOrdinalParse:/\d{1,2}م/,ordinal:"%dم",week:{dow:6,doy:12}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(130);var n=t(1);n.datepickerLocale("fi","fi",{closeText:"Sulje",prevText:"«Edellinen",nextText:"Seuraava»",currentText:"Tänään",monthNames:["Tammikuu","Helmikuu","Maaliskuu","Huhtikuu","Toukokuu","Kesäkuu","Heinäkuu","Elokuu","Syyskuu","Lokakuu","Marraskuu","Joulukuu"],monthNamesShort:["Tammi","Helmi","Maalis","Huhti","Touko","Kesä","Heinä","Elo","Syys","Loka","Marras","Joulu"],dayNamesShort:["Su","Ma","Ti","Ke","To","Pe","La"],dayNames:["Sunnuntai","Maanantai","Tiistai","Keskiviikko","Torstai","Perjantai","Lauantai"],dayNamesMin:["Su","Ma","Ti","Ke","To","Pe","La"],weekHeader:"Vk",dateFormat:"d.m.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("fi",{buttonText:{month:"Kuukausi",week:"Viikko",day:"Päivä",list:"Tapahtumat"},allDayText:"Koko päivä",eventLimitText:"lisää",noEventsMessage:"Ei näytettäviä tapahtumia"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){function a(e,a,n,r){var s="";switch(n){case"s":return r?"muutaman sekunnin":"muutama sekunti";case"ss":return r?"sekunnin":"sekuntia";case"m":return r?"minuutin":"minuutti";case"mm":s=r?"minuutin":"minuuttia";break;case"h":return r?"tunnin":"tunti";case"hh":s=r?"tunnin":"tuntia";break;case"d":return r?"päivän":"päivä";case"dd":s=r?"päivän":"päivää";break;case"M":return r?"kuukauden":"kuukausi";case"MM":s=r?"kuukauden":"kuukautta";break;case"y":return r?"vuoden":"vuosi";case"yy":s=r?"vuoden":"vuotta"}return s=t(e,r)+" "+s}function t(e,a){return e<10?a?r[e]:n[e]:e}var n="nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän".split(" "),r=["nolla","yhden","kahden","kolmen","neljän","viiden","kuuden",n[7],n[8],n[9]];return e.defineLocale("fi",{months:"tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu".split("_"),monthsShort:"tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu".split("_"),weekdays:"sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai".split("_"),weekdaysShort:"su_ma_ti_ke_to_pe_la".split("_"),weekdaysMin:"su_ma_ti_ke_to_pe_la".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD.MM.YYYY",LL:"Do MMMM[ta] YYYY",LLL:"Do MMMM[ta] YYYY, [klo] HH.mm",LLLL:"dddd, Do MMMM[ta] YYYY, [klo] HH.mm",l:"D.M.YYYY",ll:"Do MMM YYYY",lll:"Do MMM YYYY, [klo] HH.mm",llll:"ddd, Do MMM YYYY, [klo] HH.mm"},calendar:{sameDay:"[tänään] [klo] LT",nextDay:"[huomenna] [klo] LT",nextWeek:"dddd [klo] LT",lastDay:"[eilen] [klo] LT",lastWeek:"[viime] dddd[na] [klo] LT",sameElse:"L"},relativeTime:{future:"%s päästä",past:"%s sitten",s:a,ss:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(132);var n=t(1);n.datepickerLocale("fr-ca","fr-CA",{closeText:"Fermer",prevText:"Précédent",nextText:"Suivant",currentText:"Aujourd'hui",monthNames:["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],monthNamesShort:["janv.","févr.","mars","avril","mai","juin","juil.","août","sept.","oct.","nov.","déc."],dayNames:["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],dayNamesShort:["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],dayNamesMin:["D","L","M","M","J","V","S"],weekHeader:"Sem.",dateFormat:"yy-mm-dd",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("fr-ca",{buttonText:{year:"Année",month:"Mois",week:"Semaine",day:"Jour",list:"Mon planning"},allDayHtml:"Toute la
journée",eventLimitText:"en plus",noEventsMessage:"Aucun événement à afficher"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("fr-ca",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),monthsParseExact:!0,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"di_lu_ma_me_je_ve_sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd’hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",ss:"%d secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},dayOfMonthOrdinalParse:/\d{1,2}(er|e)/,ordinal:function(e,a){switch(a){default:case"M":case"Q":case"D":case"DDD":case"d":return e+(1===e?"er":"e");case"w":case"W":return e+(1===e?"re":"e")}}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(134);var n=t(1);n.datepickerLocale("fr-ch","fr-CH",{closeText:"Fermer",prevText:"<Préc",nextText:"Suiv>",currentText:"Courant",monthNames:["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],monthNamesShort:["janv.","févr.","mars","avril","mai","juin","juil.","août","sept.","oct.","nov.","déc."],dayNames:["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],dayNamesShort:["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],dayNamesMin:["D","L","M","M","J","V","S"],weekHeader:"Sm",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("fr-ch",{buttonText:{year:"Année",month:"Mois",week:"Semaine",day:"Jour",list:"Mon planning"},allDayHtml:"Toute la
journée",eventLimitText:"en plus",noEventsMessage:"Aucun événement à afficher"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("fr-ch",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),monthsParseExact:!0,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"di_lu_ma_me_je_ve_sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd’hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",ss:"%d secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},dayOfMonthOrdinalParse:/\d{1,2}(er|e)/,ordinal:function(e,a){switch(a){default:case"M":case"Q":case"D":case"DDD":case"d":return e+(1===e?"er":"e");case"w":case"W":return e+(1===e?"re":"e")}},week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(136);var n=t(1);n.datepickerLocale("fr","fr",{closeText:"Fermer",prevText:"Précédent",nextText:"Suivant",currentText:"Aujourd'hui",monthNames:["janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre"],monthNamesShort:["janv.","févr.","mars","avr.","mai","juin","juil.","août","sept.","oct.","nov.","déc."],dayNames:["dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"],dayNamesShort:["dim.","lun.","mar.","mer.","jeu.","ven.","sam."],dayNamesMin:["D","L","M","M","J","V","S"],weekHeader:"Sem.",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("fr",{buttonText:{year:"Année",month:"Mois",week:"Semaine",day:"Jour",list:"Mon planning"},allDayHtml:"Toute la
journée",eventLimitText:"en plus",noEventsMessage:"Aucun événement à afficher"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("fr",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),monthsParseExact:!0,weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"di_lu_ma_me_je_ve_sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Aujourd’hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",ss:"%d secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},dayOfMonthOrdinalParse:/\d{1,2}(er|)/,ordinal:function(e,a){switch(a){case"D":return e+(1===e?"er":"");default:case"M":case"Q":case"DDD":case"d":return e+(1===e?"er":"e");case"w":case"W":return e+(1===e?"re":"e")}},week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(138);var n=t(1);n.datepickerLocale("gl","gl",{closeText:"Pechar",prevText:"<Ant",nextText:"Seg>",currentText:"Hoxe",monthNames:["Xaneiro","Febreiro","Marzo","Abril","Maio","Xuño","Xullo","Agosto","Setembro","Outubro","Novembro","Decembro"],monthNamesShort:["Xan","Feb","Mar","Abr","Mai","Xuñ","Xul","Ago","Set","Out","Nov","Dec"],dayNames:["Domingo","Luns","Martes","Mércores","Xoves","Venres","Sábado"],dayNamesShort:["Dom","Lun","Mar","Mér","Xov","Ven","Sáb"],dayNamesMin:["Do","Lu","Ma","Mé","Xo","Ve","Sá"],weekHeader:"Sm",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("gl",{buttonText:{month:"Mes",week:"Semana",day:"Día",list:"Axenda"},allDayHtml:"Todo
o día",eventLimitText:"máis",noEventsMessage:"Non hai eventos para amosar"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("gl",{months:"xaneiro_febreiro_marzo_abril_maio_xuño_xullo_agosto_setembro_outubro_novembro_decembro".split("_"),monthsShort:"xan._feb._mar._abr._mai._xuñ._xul._ago._set._out._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"domingo_luns_martes_mércores_xoves_venres_sábado".split("_"),weekdaysShort:"dom._lun._mar._mér._xov._ven._sáb.".split("_"),weekdaysMin:"do_lu_ma_mé_xo_ve_sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY H:mm",LLLL:"dddd, D [de] MMMM [de] YYYY H:mm"},calendar:{sameDay:function(){return"[hoxe "+(1!==this.hours()?"ás":"á")+"] LT"},nextDay:function(){return"[mañá "+(1!==this.hours()?"ás":"á")+"] LT"},nextWeek:function(){return"dddd ["+(1!==this.hours()?"ás":"a")+"] LT"},lastDay:function(){return"[onte "+(1!==this.hours()?"á":"a")+"] LT"},lastWeek:function(){return"[o] dddd [pasado "+(1!==this.hours()?"ás":"a")+"] LT"},sameElse:"L"},relativeTime:{future:function(e){return 0===e.indexOf("un")?"n"+e:"en "+e},past:"hai %s",s:"uns segundos",ss:"%d segundos",m:"un minuto",mm:"%d minutos",h:"unha hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un ano",yy:"%d anos"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(140);var n=t(1);n.datepickerLocale("he","he",{closeText:"סגור",prevText:"<הקודם",nextText:"הבא>",currentText:"היום",monthNames:["ינואר","פברואר","מרץ","אפריל","מאי","יוני","יולי","אוגוסט","ספטמבר","אוקטובר","נובמבר","דצמבר"],monthNamesShort:["ינו","פבר","מרץ","אפר","מאי","יוני","יולי","אוג","ספט","אוק","נוב","דצמ"],dayNames:["ראשון","שני","שלישי","רביעי","חמישי","שישי","שבת"],dayNamesShort:["א'","ב'","ג'","ד'","ה'","ו'","שבת"],dayNamesMin:["א'","ב'","ג'","ד'","ה'","ו'","שבת"],weekHeader:"Wk",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!0,showMonthAfterYear:!1,yearSuffix:""}),n.locale("he",{buttonText:{month:"חודש",week:"שבוע",day:"יום",list:"סדר יום"},allDayText:"כל היום",eventLimitText:"אחר",noEventsMessage:"אין אירועים להצגה",weekNumberTitle:"שבוע"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("he",{months:"ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר".split("_"),monthsShort:"ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳".split("_"),weekdays:"ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת".split("_"),weekdaysShort:"א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳".split("_"),weekdaysMin:"א_ב_ג_ד_ה_ו_ש".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [ב]MMMM YYYY",LLL:"D [ב]MMMM YYYY HH:mm",LLLL:"dddd, D [ב]MMMM YYYY HH:mm",l:"D/M/YYYY",ll:"D MMM YYYY",lll:"D MMM YYYY HH:mm",llll:"ddd, D MMM YYYY HH:mm"},calendar:{sameDay:"[היום ב־]LT",nextDay:"[מחר ב־]LT",nextWeek:"dddd [בשעה] LT",lastDay:"[אתמול ב־]LT",lastWeek:"[ביום] dddd [האחרון בשעה] LT",sameElse:"L"},relativeTime:{future:"בעוד %s",past:"לפני %s",s:"מספר שניות",ss:"%d שניות",m:"דקה",mm:"%d דקות",h:"שעה",hh:function(e){return 2===e?"שעתיים":e+" שעות"},d:"יום",dd:function(e){return 2===e?"יומיים":e+" ימים"},M:"חודש",MM:function(e){return 2===e?"חודשיים":e+" חודשים"},y:"שנה",yy:function(e){return 2===e?"שנתיים":e%10==0&&10!==e?e+" שנה":e+" שנים"}},meridiemParse:/אחה"צ|לפנה"צ|אחרי הצהריים|לפני הצהריים|לפנות בוקר|בבוקר|בערב/i,isPM:function(e){return/^(אחה"צ|אחרי הצהריים|בערב)$/.test(e)},meridiem:function(e,a,t){return e<5?"לפנות בוקר":e<10?"בבוקר":e<12?t?'לפנה"צ':"לפני הצהריים":e<18?t?'אחה"צ':"אחרי הצהריים":"בערב"}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(142);var n=t(1);n.datepickerLocale("hi","hi",{closeText:"बंद",prevText:"पिछला",nextText:"अगला",currentText:"आज",monthNames:["जनवरी ","फरवरी","मार्च","अप्रेल","मई","जून","जूलाई","अगस्त ","सितम्बर","अक्टूबर","नवम्बर","दिसम्बर"],monthNamesShort:["जन","फर","मार्च","अप्रेल","मई","जून","जूलाई","अग","सित","अक्ट","नव","दि"],dayNames:["रविवार","सोमवार","मंगलवार","बुधवार","गुरुवार","शुक्रवार","शनिवार"],dayNamesShort:["रवि","सोम","मंगल","बुध","गुरु","शुक्र","शनि"],dayNamesMin:["रवि","सोम","मंगल","बुध","गुरु","शुक्र","शनि"],weekHeader:"हफ्ता",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("hi",{buttonText:{month:"महीना",week:"सप्ताह",day:"दिन",list:"कार्यसूची"},allDayText:"सभी दिन",eventLimitText:function(e){return"+अधिक "+e},noEventsMessage:"कोई घटनाओं को प्रदर्शित करने के लिए"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){var a={1:"१",2:"२",3:"३",4:"४",5:"५",6:"६",7:"७",8:"८",9:"९",0:"०"},t={"१":"1","२":"2","३":"3","४":"4","५":"5","६":"6","७":"7","८":"8","९":"9","०":"0"};return e.defineLocale("hi",{months:"जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर".split("_"),monthsShort:"जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.".split("_"),monthsParseExact:!0,weekdays:"रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार".split("_"),weekdaysShort:"रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि".split("_"),weekdaysMin:"र_सो_मं_बु_गु_शु_श".split("_"),longDateFormat:{LT:"A h:mm बजे",LTS:"A h:mm:ss बजे",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, A h:mm बजे",LLLL:"dddd, D MMMM YYYY, A h:mm बजे"},calendar:{sameDay:"[आज] LT",nextDay:"[कल] LT",nextWeek:"dddd, LT",lastDay:"[कल] LT",lastWeek:"[पिछले] dddd, LT",sameElse:"L"},relativeTime:{future:"%s में",past:"%s पहले",s:"कुछ ही क्षण",ss:"%d सेकंड",m:"एक मिनट",mm:"%d मिनट",h:"एक घंटा",hh:"%d घंटे",d:"एक दिन",dd:"%d दिन",M:"एक महीने",MM:"%d महीने",y:"एक वर्ष",yy:"%d वर्ष"},preparse:function(e){return e.replace(/[१२३४५६७८९०]/g,function(e){return t[e]})},postformat:function(e){return e.replace(/\d/g,function(e){return a[e]})},meridiemParse:/रात|सुबह|दोपहर|शाम/,meridiemHour:function(e,a){return 12===e&&(e=0),"रात"===a?e<4?e:e+12:"सुबह"===a?e:"दोपहर"===a?e>=10?e:e+12:"शाम"===a?e+12:void 0},meridiem:function(e,a,t){return e<4?"रात":e<10?"सुबह":e<17?"दोपहर":e<20?"शाम":"रात"},week:{dow:0,doy:6}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(144);var n=t(1);n.datepickerLocale("hr","hr",{closeText:"Zatvori",prevText:"<",nextText:">",currentText:"Danas",monthNames:["Siječanj","Veljača","Ožujak","Travanj","Svibanj","Lipanj","Srpanj","Kolovoz","Rujan","Listopad","Studeni","Prosinac"],monthNamesShort:["Sij","Velj","Ožu","Tra","Svi","Lip","Srp","Kol","Ruj","Lis","Stu","Pro"],dayNames:["Nedjelja","Ponedjeljak","Utorak","Srijeda","Četvrtak","Petak","Subota"],dayNamesShort:["Ned","Pon","Uto","Sri","Čet","Pet","Sub"],dayNamesMin:["Ne","Po","Ut","Sr","Če","Pe","Su"],weekHeader:"Tje",dateFormat:"dd.mm.yy.",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("hr",{buttonText:{prev:"Prijašnji",next:"Sljedeći",month:"Mjesec",week:"Tjedan",day:"Dan",list:"Raspored"},allDayText:"Cijeli dan",eventLimitText:function(e){return"+ još "+e},noEventsMessage:"Nema događaja za prikaz"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){function a(e,a,t){var n=e+" ";switch(t){case"ss":return n+=1===e?"sekunda":2===e||3===e||4===e?"sekunde":"sekundi";case"m":return a?"jedna minuta":"jedne minute";case"mm":return n+=1===e?"minuta":2===e||3===e||4===e?"minute":"minuta";case"h":return a?"jedan sat":"jednog sata";case"hh":return n+=1===e?"sat":2===e||3===e||4===e?"sata":"sati";case"dd":return n+=1===e?"dan":"dana";case"MM":return n+=1===e?"mjesec":2===e||3===e||4===e?"mjeseca":"mjeseci";case"yy":return n+=1===e?"godina":2===e||3===e||4===e?"godine":"godina"}}return e.defineLocale("hr",{months:{format:"siječnja_veljače_ožujka_travnja_svibnja_lipnja_srpnja_kolovoza_rujna_listopada_studenoga_prosinca".split("_"),standalone:"siječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac".split("_")},monthsShort:"sij._velj._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.".split("_"),monthsParseExact:!0,weekdays:"nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[jučer u] LT",lastWeek:function(){switch(this.day()){case 0:case 3:return"[prošlu] dddd [u] LT";case 6:return"[prošle] [subote] [u] LT";case 1:case 2:case 4:case 5:return"[prošli] dddd [u] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"par sekundi",ss:a,m:a,mm:a,h:a,hh:a,d:"dan",dd:a,M:"mjesec",MM:a,y:"godinu",yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(146);var n=t(1);n.datepickerLocale("hu","hu",{closeText:"bezár",prevText:"vissza",nextText:"előre",currentText:"ma",monthNames:["Január","Február","Március","Április","Május","Június","Július","Augusztus","Szeptember","Október","November","December"],monthNamesShort:["Jan","Feb","Már","Ápr","Máj","Jún","Júl","Aug","Szep","Okt","Nov","Dec"],dayNames:["Vasárnap","Hétfő","Kedd","Szerda","Csütörtök","Péntek","Szombat"],dayNamesShort:["Vas","Hét","Ked","Sze","Csü","Pén","Szo"],dayNamesMin:["V","H","K","Sze","Cs","P","Szo"],weekHeader:"Hét",dateFormat:"yy.mm.dd.",firstDay:1,isRTL:!1,showMonthAfterYear:!0,yearSuffix:""}),n.locale("hu",{buttonText:{month:"Hónap",week:"Hét",day:"Nap",list:"Napló"},allDayText:"Egész nap",eventLimitText:"további",noEventsMessage:"Nincs megjeleníthető esemény"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){function a(e,a,t,n){var r=e;switch(t){case"s":return n||a?"néhány másodperc":"néhány másodperce";case"ss":return r+(n||a)?" másodperc":" másodperce";case"m":return"egy"+(n||a?" perc":" perce");case"mm":return r+(n||a?" perc":" perce");case"h":return"egy"+(n||a?" óra":" órája");case"hh":return r+(n||a?" óra":" órája");case"d":return"egy"+(n||a?" nap":" napja");case"dd":return r+(n||a?" nap":" napja");case"M":return"egy"+(n||a?" hónap":" hónapja");case"MM":return r+(n||a?" hónap":" hónapja");case"y":return"egy"+(n||a?" év":" éve");case"yy":return r+(n||a?" év":" éve")}return""}function t(e){return(e?"":"[múlt] ")+"["+n[this.day()]+"] LT[-kor]"}var n="vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton".split(" ");return e.defineLocale("hu",{months:"január_február_március_április_május_június_július_augusztus_szeptember_október_november_december".split("_"),monthsShort:"jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec".split("_"),weekdays:"vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat".split("_"),weekdaysShort:"vas_hét_kedd_sze_csüt_pén_szo".split("_"),weekdaysMin:"v_h_k_sze_cs_p_szo".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"YYYY.MM.DD.",LL:"YYYY. MMMM D.",LLL:"YYYY. MMMM D. H:mm",LLLL:"YYYY. MMMM D., dddd H:mm"},meridiemParse:/de|du/i,isPM:function(e){return"u"===e.charAt(1).toLowerCase()},meridiem:function(e,a,t){return e<12?!0===t?"de":"DE":!0===t?"du":"DU"},calendar:{sameDay:"[ma] LT[-kor]",nextDay:"[holnap] LT[-kor]",nextWeek:function(){return t.call(this,!0)},lastDay:"[tegnap] LT[-kor]",lastWeek:function(){return t.call(this,!1)},sameElse:"L"},relativeTime:{future:"%s múlva",past:"%s",s:a,ss:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(148);var n=t(1);n.datepickerLocale("id","id",{closeText:"Tutup",prevText:"<mundur",nextText:"maju>",currentText:"hari ini",monthNames:["Januari","Februari","Maret","April","Mei","Juni","Juli","Agustus","September","Oktober","Nopember","Desember"],monthNamesShort:["Jan","Feb","Mar","Apr","Mei","Jun","Jul","Agus","Sep","Okt","Nop","Des"],dayNames:["Minggu","Senin","Selasa","Rabu","Kamis","Jumat","Sabtu"],dayNamesShort:["Min","Sen","Sel","Rab","kam","Jum","Sab"],dayNamesMin:["Mg","Sn","Sl","Rb","Km","jm","Sb"],weekHeader:"Mg",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("id",{buttonText:{month:"Bulan",week:"Minggu",day:"Hari",list:"Agenda"},allDayHtml:"Sehari
penuh",eventLimitText:"lebih",noEventsMessage:"Tidak ada acara untuk ditampilkan"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("id",{months:"Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Mei_Jun_Jul_Agt_Sep_Okt_Nov_Des".split("_"),weekdays:"Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu".split("_"),weekdaysShort:"Min_Sen_Sel_Rab_Kam_Jum_Sab".split("_"),weekdaysMin:"Mg_Sn_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/pagi|siang|sore|malam/,meridiemHour:function(e,a){return 12===e&&(e=0),"pagi"===a?e:"siang"===a?e>=11?e:e+12:"sore"===a||"malam"===a?e+12:void 0},meridiem:function(e,a,t){return e<11?"pagi":e<15?"siang":e<19?"sore":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Besok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kemarin pukul] LT",lastWeek:"dddd [lalu pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lalu",s:"beberapa detik",ss:"%d detik",m:"semenit",mm:"%d menit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,doy:7}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(150);var n=t(1);n.datepickerLocale("is","is",{closeText:"Loka",prevText:"< Fyrri",nextText:"Næsti >",currentText:"Í dag",monthNames:["Janúar","Febrúar","Mars","Apríl","Maí","Júní","Júlí","Ágúst","September","Október","Nóvember","Desember"],monthNamesShort:["Jan","Feb","Mar","Apr","Maí","Jún","Júl","Ágú","Sep","Okt","Nóv","Des"],dayNames:["Sunnudagur","Mánudagur","Þriðjudagur","Miðvikudagur","Fimmtudagur","Föstudagur","Laugardagur"],dayNamesShort:["Sun","Mán","Þri","Mið","Fim","Fös","Lau"],dayNamesMin:["Su","Má","Þr","Mi","Fi","Fö","La"],weekHeader:"Vika",dateFormat:"dd.mm.yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("is",{buttonText:{month:"Mánuður",week:"Vika",day:"Dagur",list:"Dagskrá"},allDayHtml:"Allan
daginn",eventLimitText:"meira",noEventsMessage:"Engir viðburðir til að sýna"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){function a(e){return e%100==11||e%10!=1}function t(e,t,n,r){var s=e+" ";switch(n){case"s":return t||r?"nokkrar sekúndur":"nokkrum sekúndum";case"ss":return a(e)?s+(t||r?"sekúndur":"sekúndum"):s+"sekúnda";case"m":return t?"mínúta":"mínútu";case"mm":return a(e)?s+(t||r?"mínútur":"mínútum"):t?s+"mínúta":s+"mínútu";case"hh":return a(e)?s+(t||r?"klukkustundir":"klukkustundum"):s+"klukkustund";case"d":return t?"dagur":r?"dag":"degi";case"dd":return a(e)?t?s+"dagar":s+(r?"daga":"dögum"):t?s+"dagur":s+(r?"dag":"degi");case"M":return t?"mánuður":r?"mánuð":"mánuði";case"MM":return a(e)?t?s+"mánuðir":s+(r?"mánuði":"mánuðum"):t?s+"mánuður":s+(r?"mánuð":"mánuði");case"y":return t||r?"ár":"ári";case"yy":return a(e)?s+(t||r?"ár":"árum"):s+(t||r?"ár":"ári")}}return e.defineLocale("is",{months:"janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember".split("_"),monthsShort:"jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des".split("_"),weekdays:"sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur".split("_"),weekdaysShort:"sun_mán_þri_mið_fim_fös_lau".split("_"),weekdaysMin:"Su_Má_Þr_Mi_Fi_Fö_La".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] H:mm",LLLL:"dddd, D. MMMM YYYY [kl.] H:mm"},calendar:{sameDay:"[í dag kl.] LT",nextDay:"[á morgun kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[í gær kl.] LT",lastWeek:"[síðasta] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"eftir %s",past:"fyrir %s síðan",s:t,ss:t,m:t,mm:t,h:"klukkustund",hh:t,d:t,dd:t,M:t,MM:t,y:t,yy:t},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(152);var n=t(1);n.datepickerLocale("it","it",{closeText:"Chiudi",prevText:"<Prec",nextText:"Succ>",currentText:"Oggi",monthNames:["Gennaio","Febbraio","Marzo","Aprile","Maggio","Giugno","Luglio","Agosto","Settembre","Ottobre","Novembre","Dicembre"],monthNamesShort:["Gen","Feb","Mar","Apr","Mag","Giu","Lug","Ago","Set","Ott","Nov","Dic"],dayNames:["Domenica","Lunedì","Martedì","Mercoledì","Giovedì","Venerdì","Sabato"],dayNamesShort:["Dom","Lun","Mar","Mer","Gio","Ven","Sab"],dayNamesMin:["Do","Lu","Ma","Me","Gi","Ve","Sa"],weekHeader:"Sm",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("it",{buttonText:{month:"Mese",week:"Settimana",day:"Giorno",list:"Agenda"},allDayHtml:"Tutto il
giorno",eventLimitText:function(e){return"+altri "+e},noEventsMessage:"Non ci sono eventi da visualizzare"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("it",{months:"gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre".split("_"),monthsShort:"gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic".split("_"),weekdays:"domenica_lunedì_martedì_mercoledì_giovedì_venerdì_sabato".split("_"),weekdaysShort:"dom_lun_mar_mer_gio_ven_sab".split("_"),weekdaysMin:"do_lu_ma_me_gi_ve_sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[Oggi alle] LT",nextDay:"[Domani alle] LT",nextWeek:"dddd [alle] LT",lastDay:"[Ieri alle] LT",lastWeek:function(){switch(this.day()){case 0:return"[la scorsa] dddd [alle] LT";default:return"[lo scorso] dddd [alle] LT"}},sameElse:"L"},relativeTime:{future:function(e){return(/^[0-9].+$/.test(e)?"tra":"in")+" "+e},past:"%s fa",s:"alcuni secondi",ss:"%d secondi",m:"un minuto",mm:"%d minuti",h:"un'ora",hh:"%d ore",d:"un giorno",dd:"%d giorni",M:"un mese",MM:"%d mesi",y:"un anno",yy:"%d anni"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(154);var n=t(1);n.datepickerLocale("ja","ja",{closeText:"閉じる",prevText:"<前",nextText:"次>",currentText:"今日",monthNames:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],monthNamesShort:["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"],dayNames:["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"],dayNamesShort:["日","月","火","水","木","金","土"],dayNamesMin:["日","月","火","水","木","金","土"],weekHeader:"週",dateFormat:"yy/mm/dd",firstDay:0,isRTL:!1,showMonthAfterYear:!0,yearSuffix:"年"}),n.locale("ja",{ +buttonText:{month:"月",week:"週",day:"日",list:"予定リスト"},allDayText:"終日",eventLimitText:function(e){return"他 "+e+" 件"},noEventsMessage:"表示する予定はありません"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("ja",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"),weekdaysShort:"日_月_火_水_木_金_土".split("_"),weekdaysMin:"日_月_火_水_木_金_土".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日 HH:mm",LLLL:"YYYY年M月D日 dddd HH:mm",l:"YYYY/MM/DD",ll:"YYYY年M月D日",lll:"YYYY年M月D日 HH:mm",llll:"YYYY年M月D日(ddd) HH:mm"},meridiemParse:/午前|午後/i,isPM:function(e){return"午後"===e},meridiem:function(e,a,t){return e<12?"午前":"午後"},calendar:{sameDay:"[今日] LT",nextDay:"[明日] LT",nextWeek:function(e){return e.week()=100?100:null;return e+(a[e]||a[t]||a[n])},week:{dow:1,doy:7}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(160);var n=t(1);n.datepickerLocale("ko","ko",{closeText:"닫기",prevText:"이전달",nextText:"다음달",currentText:"오늘",monthNames:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],monthNamesShort:["1월","2월","3월","4월","5월","6월","7월","8월","9월","10월","11월","12월"],dayNames:["일요일","월요일","화요일","수요일","목요일","금요일","토요일"],dayNamesShort:["일","월","화","수","목","금","토"],dayNamesMin:["일","월","화","수","목","금","토"],weekHeader:"주",dateFormat:"yy. m. d.",firstDay:0,isRTL:!1,showMonthAfterYear:!0,yearSuffix:"년"}),n.locale("ko",{buttonText:{month:"월",week:"주",day:"일",list:"일정목록"},allDayText:"종일",eventLimitText:"개",noEventsMessage:"일정이 없습니다"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("ko",{months:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),monthsShort:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),weekdays:"일요일_월요일_화요일_수요일_목요일_금요일_토요일".split("_"),weekdaysShort:"일_월_화_수_목_금_토".split("_"),weekdaysMin:"일_월_화_수_목_금_토".split("_"),longDateFormat:{LT:"A h:mm",LTS:"A h:mm:ss",L:"YYYY.MM.DD.",LL:"YYYY년 MMMM D일",LLL:"YYYY년 MMMM D일 A h:mm",LLLL:"YYYY년 MMMM D일 dddd A h:mm",l:"YYYY.MM.DD.",ll:"YYYY년 MMMM D일",lll:"YYYY년 MMMM D일 A h:mm",llll:"YYYY년 MMMM D일 dddd A h:mm"},calendar:{sameDay:"오늘 LT",nextDay:"내일 LT",nextWeek:"dddd LT",lastDay:"어제 LT",lastWeek:"지난주 dddd LT",sameElse:"L"},relativeTime:{future:"%s 후",past:"%s 전",s:"몇 초",ss:"%d초",m:"1분",mm:"%d분",h:"한 시간",hh:"%d시간",d:"하루",dd:"%d일",M:"한 달",MM:"%d달",y:"일 년",yy:"%d년"},dayOfMonthOrdinalParse:/\d{1,2}(일|월|주)/,ordinal:function(e,a){switch(a){case"d":case"D":case"DDD":return e+"일";case"M":return e+"월";case"w":case"W":return e+"주";default:return e}},meridiemParse:/오전|오후/,isPM:function(e){return"오후"===e},meridiem:function(e,a,t){return e<12?"오전":"오후"}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(162);var n=t(1);n.datepickerLocale("lb","lb",{closeText:"Fäerdeg",prevText:"Zréck",nextText:"Weider",currentText:"Haut",monthNames:["Januar","Februar","Mäerz","Abrëll","Mee","Juni","Juli","August","September","Oktober","November","Dezember"],monthNamesShort:["Jan","Feb","Mäe","Abr","Mee","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],dayNames:["Sonndeg","Méindeg","Dënschdeg","Mëttwoch","Donneschdeg","Freideg","Samschdeg"],dayNamesShort:["Son","Méi","Dën","Mët","Don","Fre","Sam"],dayNamesMin:["So","Mé","Dë","Më","Do","Fr","Sa"],weekHeader:"W",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("lb",{buttonText:{month:"Mount",week:"Woch",day:"Dag",list:"Terminiwwersiicht"},allDayText:"Ganzen Dag",eventLimitText:"méi",noEventsMessage:"Nee Evenementer ze affichéieren"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){function a(e,a,t,n){var r={m:["eng Minutt","enger Minutt"],h:["eng Stonn","enger Stonn"],d:["een Dag","engem Dag"],M:["ee Mount","engem Mount"],y:["ee Joer","engem Joer"]};return a?r[t][0]:r[t][1]}function t(e){return r(e.substr(0,e.indexOf(" ")))?"a "+e:"an "+e}function n(e){return r(e.substr(0,e.indexOf(" ")))?"viru "+e:"virun "+e}function r(e){if(e=parseInt(e,10),isNaN(e))return!1;if(e<0)return!0;if(e<10)return 4<=e&&e<=7;if(e<100){var a=e%10,t=e/10;return r(0===a?t:a)}if(e<1e4){for(;e>=10;)e/=10;return r(e)}return e/=1e3,r(e)}return e.defineLocale("lb",{months:"Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),monthsParseExact:!0,weekdays:"Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg".split("_"),weekdaysShort:"So._Mé._Dë._Më._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mé_Dë_Më_Do_Fr_Sa".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm [Auer]",LTS:"H:mm:ss [Auer]",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm [Auer]",LLLL:"dddd, D. MMMM YYYY H:mm [Auer]"},calendar:{sameDay:"[Haut um] LT",sameElse:"L",nextDay:"[Muer um] LT",nextWeek:"dddd [um] LT",lastDay:"[Gëschter um] LT",lastWeek:function(){switch(this.day()){case 2:case 4:return"[Leschten] dddd [um] LT";default:return"[Leschte] dddd [um] LT"}}},relativeTime:{future:t,past:n,s:"e puer Sekonnen",ss:"%d Sekonnen",m:a,mm:"%d Minutten",h:a,hh:"%d Stonnen",d:a,dd:"%d Deeg",M:a,MM:"%d Méint",y:a,yy:"%d Joer"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(164);var n=t(1);n.datepickerLocale("lt","lt",{closeText:"Uždaryti",prevText:"<Atgal",nextText:"Pirmyn>",currentText:"Šiandien",monthNames:["Sausis","Vasaris","Kovas","Balandis","Gegužė","Birželis","Liepa","Rugpjūtis","Rugsėjis","Spalis","Lapkritis","Gruodis"],monthNamesShort:["Sau","Vas","Kov","Bal","Geg","Bir","Lie","Rugp","Rugs","Spa","Lap","Gru"],dayNames:["sekmadienis","pirmadienis","antradienis","trečiadienis","ketvirtadienis","penktadienis","šeštadienis"],dayNamesShort:["sek","pir","ant","tre","ket","pen","šeš"],dayNamesMin:["Se","Pr","An","Tr","Ke","Pe","Še"],weekHeader:"SAV",dateFormat:"yy-mm-dd",firstDay:1,isRTL:!1,showMonthAfterYear:!0,yearSuffix:""}),n.locale("lt",{buttonText:{month:"Mėnuo",week:"Savaitė",day:"Diena",list:"Darbotvarkė"},allDayText:"Visą dieną",eventLimitText:"daugiau",noEventsMessage:"Nėra įvykių rodyti"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){function a(e,a,t,n){return a?"kelios sekundės":n?"kelių sekundžių":"kelias sekundes"}function t(e,a,t,n){return a?r(t)[0]:n?r(t)[1]:r(t)[2]}function n(e){return e%10==0||e>10&&e<20}function r(e){return d[e].split("_")}function s(e,a,s,d){var i=e+" ";return 1===e?i+t(e,a,s[0],d):a?i+(n(e)?r(s)[1]:r(s)[0]):d?i+r(s)[1]:i+(n(e)?r(s)[1]:r(s)[2])}var d={ss:"sekundė_sekundžių_sekundes",m:"minutė_minutės_minutę",mm:"minutės_minučių_minutes",h:"valanda_valandos_valandą",hh:"valandos_valandų_valandas",d:"diena_dienos_dieną",dd:"dienos_dienų_dienas",M:"mėnuo_mėnesio_mėnesį",MM:"mėnesiai_mėnesių_mėnesius",y:"metai_metų_metus",yy:"metai_metų_metus"};return e.defineLocale("lt",{months:{format:"sausio_vasario_kovo_balandžio_gegužės_birželio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio".split("_"),standalone:"sausis_vasaris_kovas_balandis_gegužė_birželis_liepa_rugpjūtis_rugsėjis_spalis_lapkritis_gruodis".split("_"),isFormat:/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|MMMM?(\[[^\[\]]*\]|\s)+D[oD]?/},monthsShort:"sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd".split("_"),weekdays:{format:"sekmadienį_pirmadienį_antradienį_trečiadienį_ketvirtadienį_penktadienį_šeštadienį".split("_"),standalone:"sekmadienis_pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis".split("_"),isFormat:/dddd HH:mm/},weekdaysShort:"Sek_Pir_Ant_Tre_Ket_Pen_Šeš".split("_"),weekdaysMin:"S_P_A_T_K_Pn_Š".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"YYYY [m.] MMMM D [d.]",LLL:"YYYY [m.] MMMM D [d.], HH:mm [val.]",LLLL:"YYYY [m.] MMMM D [d.], dddd, HH:mm [val.]",l:"YYYY-MM-DD",ll:"YYYY [m.] MMMM D [d.]",lll:"YYYY [m.] MMMM D [d.], HH:mm [val.]",llll:"YYYY [m.] MMMM D [d.], ddd, HH:mm [val.]"},calendar:{sameDay:"[Šiandien] LT",nextDay:"[Rytoj] LT",nextWeek:"dddd LT",lastDay:"[Vakar] LT",lastWeek:"[Praėjusį] dddd LT",sameElse:"L"},relativeTime:{future:"po %s",past:"prieš %s",s:a,ss:s,m:t,mm:s,h:t,hh:s,d:t,dd:s,M:t,MM:s,y:t,yy:s},dayOfMonthOrdinalParse:/\d{1,2}-oji/,ordinal:function(e){return e+"-oji"},week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(166);var n=t(1);n.datepickerLocale("lv","lv",{closeText:"Aizvērt",prevText:"Iepr.",nextText:"Nāk.",currentText:"Šodien",monthNames:["Janvāris","Februāris","Marts","Aprīlis","Maijs","Jūnijs","Jūlijs","Augusts","Septembris","Oktobris","Novembris","Decembris"],monthNamesShort:["Jan","Feb","Mar","Apr","Mai","Jūn","Jūl","Aug","Sep","Okt","Nov","Dec"],dayNames:["svētdiena","pirmdiena","otrdiena","trešdiena","ceturtdiena","piektdiena","sestdiena"],dayNamesShort:["svt","prm","otr","tre","ctr","pkt","sst"],dayNamesMin:["Sv","Pr","Ot","Tr","Ct","Pk","Ss"],weekHeader:"Ned.",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("lv",{buttonText:{month:"Mēnesis",week:"Nedēļa",day:"Diena",list:"Dienas kārtība"},allDayText:"Visu dienu",eventLimitText:function(e){return"+vēl "+e},noEventsMessage:"Nav notikumu"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){function a(e,a,t){return t?a%10==1&&a%100!=11?e[2]:e[3]:a%10==1&&a%100!=11?e[0]:e[1]}function t(e,t,n){return e+" "+a(s[n],e,t)}function n(e,t,n){return a(s[n],e,t)}function r(e,a){return a?"dažas sekundes":"dažām sekundēm"}var s={ss:"sekundes_sekundēm_sekunde_sekundes".split("_"),m:"minūtes_minūtēm_minūte_minūtes".split("_"),mm:"minūtes_minūtēm_minūte_minūtes".split("_"),h:"stundas_stundām_stunda_stundas".split("_"),hh:"stundas_stundām_stunda_stundas".split("_"),d:"dienas_dienām_diena_dienas".split("_"),dd:"dienas_dienām_diena_dienas".split("_"),M:"mēneša_mēnešiem_mēnesis_mēneši".split("_"),MM:"mēneša_mēnešiem_mēnesis_mēneši".split("_"),y:"gada_gadiem_gads_gadi".split("_"),yy:"gada_gadiem_gads_gadi".split("_")};return e.defineLocale("lv",{months:"janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris".split("_"),monthsShort:"jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec".split("_"),weekdays:"svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena".split("_"),weekdaysShort:"Sv_P_O_T_C_Pk_S".split("_"),weekdaysMin:"Sv_P_O_T_C_Pk_S".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY.",LL:"YYYY. [gada] D. MMMM",LLL:"YYYY. [gada] D. MMMM, HH:mm",LLLL:"YYYY. [gada] D. MMMM, dddd, HH:mm"},calendar:{sameDay:"[Šodien pulksten] LT",nextDay:"[Rīt pulksten] LT",nextWeek:"dddd [pulksten] LT",lastDay:"[Vakar pulksten] LT",lastWeek:"[Pagājušā] dddd [pulksten] LT",sameElse:"L"},relativeTime:{future:"pēc %s",past:"pirms %s",s:r,ss:t,m:n,mm:t,h:n,hh:t,d:n,dd:t,M:n,MM:t,y:n,yy:t},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(168);var n=t(1);n.datepickerLocale("mk","mk",{closeText:"Затвори",prevText:"<",nextText:">",currentText:"Денес",monthNames:["Јануари","Февруари","Март","Април","Мај","Јуни","Јули","Август","Септември","Октомври","Ноември","Декември"],monthNamesShort:["Јан","Фев","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Ное","Дек"],dayNames:["Недела","Понеделник","Вторник","Среда","Четврток","Петок","Сабота"],dayNamesShort:["Нед","Пон","Вто","Сре","Чет","Пет","Саб"],dayNamesMin:["Не","По","Вт","Ср","Че","Пе","Са"],weekHeader:"Сед",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("mk",{buttonText:{month:"Месец",week:"Недела",day:"Ден",list:"График"},allDayText:"Цел ден",eventLimitText:function(e){return"+повеќе "+e},noEventsMessage:"Нема настани за прикажување"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("mk",{months:"јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември".split("_"),monthsShort:"јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек".split("_"),weekdays:"недела_понеделник_вторник_среда_четврток_петок_сабота".split("_"),weekdaysShort:"нед_пон_вто_сре_чет_пет_саб".split("_"),weekdaysMin:"нe_пo_вт_ср_че_пе_сa".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"D.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[Денес во] LT",nextDay:"[Утре во] LT",nextWeek:"[Во] dddd [во] LT",lastDay:"[Вчера во] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[Изминатата] dddd [во] LT";case 1:case 2:case 4:case 5:return"[Изминатиот] dddd [во] LT"}},sameElse:"L"},relativeTime:{future:"после %s",past:"пред %s",s:"неколку секунди",ss:"%d секунди",m:"минута",mm:"%d минути",h:"час",hh:"%d часа",d:"ден",dd:"%d дена",M:"месец",MM:"%d месеци",y:"година",yy:"%d години"},dayOfMonthOrdinalParse:/\d{1,2}-(ев|ен|ти|ви|ри|ми)/,ordinal:function(e){var a=e%10,t=e%100;return 0===e?e+"-ев":0===t?e+"-ен":t>10&&t<20?e+"-ти":1===a?e+"-ви":2===a?e+"-ри":7===a||8===a?e+"-ми":e+"-ти"},week:{dow:1,doy:7}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(170);var n=t(1);n.datepickerLocale("ms-my","ms",{closeText:"Tutup",prevText:"<Sebelum",nextText:"Selepas>",currentText:"hari ini",monthNames:["Januari","Februari","Mac","April","Mei","Jun","Julai","Ogos","September","Oktober","November","Disember"],monthNamesShort:["Jan","Feb","Mac","Apr","Mei","Jun","Jul","Ogo","Sep","Okt","Nov","Dis"],dayNames:["Ahad","Isnin","Selasa","Rabu","Khamis","Jumaat","Sabtu"],dayNamesShort:["Aha","Isn","Sel","Rab","kha","Jum","Sab"],dayNamesMin:["Ah","Is","Se","Ra","Kh","Ju","Sa"],weekHeader:"Mg",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("ms-my",{buttonText:{month:"Bulan",week:"Minggu",day:"Hari",list:"Agenda"},allDayText:"Sepanjang hari",eventLimitText:function(e){return"masih ada "+e+" acara"},noEventsMessage:"Tiada peristiwa untuk dipaparkan"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("ms-my",{months:"Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember".split("_"),monthsShort:"Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis".split("_"),weekdays:"Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu".split("_"),weekdaysShort:"Ahd_Isn_Sel_Rab_Kha_Jum_Sab".split("_"),weekdaysMin:"Ah_Is_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/pagi|tengahari|petang|malam/,meridiemHour:function(e,a){return 12===e&&(e=0),"pagi"===a?e:"tengahari"===a?e>=11?e:e+12:"petang"===a||"malam"===a?e+12:void 0},meridiem:function(e,a,t){return e<11?"pagi":e<15?"tengahari":e<19?"petang":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Esok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kelmarin pukul] LT",lastWeek:"dddd [lepas pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lepas",s:"beberapa saat",ss:"%d saat",m:"seminit",mm:"%d minit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,doy:7}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(172);var n=t(1);n.datepickerLocale("ms","ms",{closeText:"Tutup",prevText:"<Sebelum",nextText:"Selepas>",currentText:"hari ini",monthNames:["Januari","Februari","Mac","April","Mei","Jun","Julai","Ogos","September","Oktober","November","Disember"],monthNamesShort:["Jan","Feb","Mac","Apr","Mei","Jun","Jul","Ogo","Sep","Okt","Nov","Dis"],dayNames:["Ahad","Isnin","Selasa","Rabu","Khamis","Jumaat","Sabtu"],dayNamesShort:["Aha","Isn","Sel","Rab","kha","Jum","Sab"],dayNamesMin:["Ah","Is","Se","Ra","Kh","Ju","Sa"],weekHeader:"Mg",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("ms",{buttonText:{month:"Bulan",week:"Minggu",day:"Hari",list:"Agenda"},allDayText:"Sepanjang hari",eventLimitText:function(e){return"masih ada "+e+" acara"},noEventsMessage:"Tiada peristiwa untuk dipaparkan"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("ms",{months:"Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember".split("_"),monthsShort:"Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis".split("_"),weekdays:"Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu".split("_"),weekdaysShort:"Ahd_Isn_Sel_Rab_Kha_Jum_Sab".split("_"),weekdaysMin:"Ah_Is_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",LTS:"HH.mm.ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] HH.mm",LLLL:"dddd, D MMMM YYYY [pukul] HH.mm"},meridiemParse:/pagi|tengahari|petang|malam/,meridiemHour:function(e,a){return 12===e&&(e=0),"pagi"===a?e:"tengahari"===a?e>=11?e:e+12:"petang"===a||"malam"===a?e+12:void 0},meridiem:function(e,a,t){return e<11?"pagi":e<15?"tengahari":e<19?"petang":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Esok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kelmarin pukul] LT",lastWeek:"dddd [lepas pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lepas",s:"beberapa saat",ss:"%d saat",m:"seminit",mm:"%d minit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,doy:7}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(174);var n=t(1);n.datepickerLocale("nb","nb",{closeText:"Lukk",prevText:"«Forrige",nextText:"Neste»",currentText:"I dag",monthNames:["januar","februar","mars","april","mai","juni","juli","august","september","oktober","november","desember"],monthNamesShort:["jan","feb","mar","apr","mai","jun","jul","aug","sep","okt","nov","des"],dayNamesShort:["søn","man","tir","ons","tor","fre","lør"],dayNames:["søndag","mandag","tirsdag","onsdag","torsdag","fredag","lørdag"],dayNamesMin:["sø","ma","ti","on","to","fr","lø"],weekHeader:"Uke",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("nb",{buttonText:{month:"Måned",week:"Uke",day:"Dag",list:"Agenda"},allDayText:"Hele dagen",eventLimitText:"til",noEventsMessage:"Ingen hendelser å vise"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("nb",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan._feb._mars_april_mai_juni_juli_aug._sep._okt._nov._des.".split("_"),monthsParseExact:!0,weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"sø._ma._ti._on._to._fr._lø.".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] HH:mm",LLLL:"dddd D. MMMM YYYY [kl.] HH:mm"},calendar:{sameDay:"[i dag kl.] LT",nextDay:"[i morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[i går kl.] LT",lastWeek:"[forrige] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"noen sekunder",ss:"%d sekunder",m:"ett minutt",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dager",M:"en måned",MM:"%d måneder",y:"ett år",yy:"%d år"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(176);var n=t(1);n.datepickerLocale("nl-be","nl-BE",{closeText:"Sluiten",prevText:"←",nextText:"→",currentText:"Vandaag",monthNames:["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],monthNamesShort:["jan","feb","mrt","apr","mei","jun","jul","aug","sep","okt","nov","dec"],dayNames:["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag"],dayNamesShort:["zon","maa","din","woe","don","vri","zat"],dayNamesMin:["zo","ma","di","wo","do","vr","za"],weekHeader:"Wk",dateFormat:"dd/mm/yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("nl-be",{buttonText:{month:"Maand",week:"Week",day:"Dag",list:"Agenda"},allDayText:"Hele dag",eventLimitText:"extra",noEventsMessage:"Geen evenementen om te laten zien"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){var a="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),t="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_"),n=[/^jan/i,/^feb/i,/^maart|mrt.?$/i,/^apr/i,/^mei$/i,/^jun[i.]?$/i,/^jul[i.]?$/i,/^aug/i,/^sep/i,/^okt/i,/^nov/i,/^dec/i],r=/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december|jan\.?|feb\.?|mrt\.?|apr\.?|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i;return e.defineLocale("nl-be",{months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(e,n){return e?/-MMM-/.test(n)?t[e.month()]:a[e.month()]:a},monthsRegex:r,monthsShortRegex:r,monthsStrictRegex:/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december)/i,monthsShortStrictRegex:/^(jan\.?|feb\.?|mrt\.?|apr\.?|mei|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,monthsParse:n,longMonthsParse:n,shortMonthsParse:n,weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"zo_ma_di_wo_do_vr_za".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[vandaag om] LT",nextDay:"[morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",ss:"%d seconden",m:"één minuut",mm:"%d minuten",h:"één uur",hh:"%d uur",d:"één dag",dd:"%d dagen",M:"één maand",MM:"%d maanden",y:"één jaar",yy:"%d jaar"},dayOfMonthOrdinalParse:/\d{1,2}(ste|de)/,ordinal:function(e){return e+(1===e||8===e||e>=20?"ste":"de")},week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(178);var n=t(1);n.datepickerLocale("nl","nl",{closeText:"Sluiten",prevText:"←",nextText:"→",currentText:"Vandaag",monthNames:["januari","februari","maart","april","mei","juni","juli","augustus","september","oktober","november","december"],monthNamesShort:["jan","feb","mrt","apr","mei","jun","jul","aug","sep","okt","nov","dec"],dayNames:["zondag","maandag","dinsdag","woensdag","donderdag","vrijdag","zaterdag"],dayNamesShort:["zon","maa","din","woe","don","vri","zat"],dayNamesMin:["zo","ma","di","wo","do","vr","za"],weekHeader:"Wk",dateFormat:"dd-mm-yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("nl",{buttonText:{year:"Jaar",month:"Maand",week:"Week",day:"Dag",list:"Agenda"},allDayText:"Hele dag",eventLimitText:"extra",noEventsMessage:"Geen evenementen om te laten zien"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){var a="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),t="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_"),n=[/^jan/i,/^feb/i,/^maart|mrt.?$/i,/^apr/i,/^mei$/i,/^jun[i.]?$/i,/^jul[i.]?$/i,/^aug/i,/^sep/i,/^okt/i,/^nov/i,/^dec/i],r=/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december|jan\.?|feb\.?|mrt\.?|apr\.?|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i;return e.defineLocale("nl",{months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(e,n){return e?/-MMM-/.test(n)?t[e.month()]:a[e.month()]:a},monthsRegex:r,monthsShortRegex:r,monthsStrictRegex:/^(januari|februari|maart|april|mei|ju[nl]i|augustus|september|oktober|november|december)/i,monthsShortStrictRegex:/^(jan\.?|feb\.?|mrt\.?|apr\.?|mei|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,monthsParse:n,longMonthsParse:n,shortMonthsParse:n,weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"zo_ma_di_wo_do_vr_za".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd D MMMM YYYY HH:mm"},calendar:{sameDay:"[vandaag om] LT",nextDay:"[morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",ss:"%d seconden",m:"één minuut",mm:"%d minuten",h:"één uur",hh:"%d uur",d:"één dag",dd:"%d dagen",M:"één maand",MM:"%d maanden",y:"één jaar",yy:"%d jaar"},dayOfMonthOrdinalParse:/\d{1,2}(ste|de)/,ordinal:function(e){return e+(1===e||8===e||e>=20?"ste":"de")},week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(180);var n=t(1);n.datepickerLocale("nn","nn",{closeText:"Lukk",prevText:"«Førre",nextText:"Neste»",currentText:"I dag",monthNames:["januar","februar","mars","april","mai","juni","juli","august","september","oktober","november","desember"],monthNamesShort:["jan","feb","mar","apr","mai","jun","jul","aug","sep","okt","nov","des"],dayNamesShort:["sun","mån","tys","ons","tor","fre","lau"],dayNames:["sundag","måndag","tysdag","onsdag","torsdag","fredag","laurdag"],dayNamesMin:["su","må","ty","on","to","fr","la"],weekHeader:"Veke",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("nn",{buttonText:{month:"Månad",week:"Veke",day:"Dag",list:"Agenda"},allDayText:"Heile dagen",eventLimitText:"til",noEventsMessage:"Ingen hendelser å vise"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("nn",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),weekdays:"sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag".split("_"),weekdaysShort:"sun_mån_tys_ons_tor_fre_lau".split("_"),weekdaysMin:"su_må_ty_on_to_fr_lø".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] H:mm",LLLL:"dddd D. MMMM YYYY [kl.] HH:mm"},calendar:{sameDay:"[I dag klokka] LT",nextDay:"[I morgon klokka] LT",nextWeek:"dddd [klokka] LT",lastDay:"[I går klokka] LT",lastWeek:"[Føregåande] dddd [klokka] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s sidan",s:"nokre sekund",ss:"%d sekund",m:"eit minutt",mm:"%d minutt",h:"ein time",hh:"%d timar",d:"ein dag",dd:"%d dagar",M:"ein månad",MM:"%d månader",y:"eit år",yy:"%d år"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(182);var n=t(1);n.datepickerLocale("pl","pl",{closeText:"Zamknij",prevText:"<Poprzedni",nextText:"Następny>",currentText:"Dziś", +monthNames:["Styczeń","Luty","Marzec","Kwiecień","Maj","Czerwiec","Lipiec","Sierpień","Wrzesień","Październik","Listopad","Grudzień"],monthNamesShort:["Sty","Lu","Mar","Kw","Maj","Cze","Lip","Sie","Wrz","Pa","Lis","Gru"],dayNames:["Niedziela","Poniedziałek","Wtorek","Środa","Czwartek","Piątek","Sobota"],dayNamesShort:["Nie","Pn","Wt","Śr","Czw","Pt","So"],dayNamesMin:["N","Pn","Wt","Śr","Cz","Pt","So"],weekHeader:"Tydz",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("pl",{buttonText:{month:"Miesiąc",week:"Tydzień",day:"Dzień",list:"Plan dnia"},allDayText:"Cały dzień",eventLimitText:"więcej",noEventsMessage:"Brak wydarzeń do wyświetlenia"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){function a(e){return e%10<5&&e%10>1&&~~(e/10)%10!=1}function t(e,t,n){var r=e+" ";switch(n){case"ss":return r+(a(e)?"sekundy":"sekund");case"m":return t?"minuta":"minutę";case"mm":return r+(a(e)?"minuty":"minut");case"h":return t?"godzina":"godzinę";case"hh":return r+(a(e)?"godziny":"godzin");case"MM":return r+(a(e)?"miesiące":"miesięcy");case"yy":return r+(a(e)?"lata":"lat")}}var n="styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień".split("_"),r="stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia".split("_");return e.defineLocale("pl",{months:function(e,a){return e?""===a?"("+r[e.month()]+"|"+n[e.month()]+")":/D MMMM/.test(a)?r[e.month()]:n[e.month()]:n},monthsShort:"sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru".split("_"),weekdays:"niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota".split("_"),weekdaysShort:"ndz_pon_wt_śr_czw_pt_sob".split("_"),weekdaysMin:"Nd_Pn_Wt_Śr_Cz_Pt_So".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Dziś o] LT",nextDay:"[Jutro o] LT",nextWeek:function(){switch(this.day()){case 0:return"[W niedzielę o] LT";case 2:return"[We wtorek o] LT";case 3:return"[W środę o] LT";case 6:return"[W sobotę o] LT";default:return"[W] dddd [o] LT"}},lastDay:"[Wczoraj o] LT",lastWeek:function(){switch(this.day()){case 0:return"[W zeszłą niedzielę o] LT";case 3:return"[W zeszłą środę o] LT";case 6:return"[W zeszłą sobotę o] LT";default:return"[W zeszły] dddd [o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"%s temu",s:"kilka sekund",ss:t,m:t,mm:t,h:t,hh:t,d:"1 dzień",dd:"%d dni",M:"miesiąc",MM:t,y:"rok",yy:t},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(184);var n=t(1);n.datepickerLocale("pt-br","pt-BR",{closeText:"Fechar",prevText:"<Anterior",nextText:"Próximo>",currentText:"Hoje",monthNames:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthNamesShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],dayNames:["Domingo","Segunda-feira","Terça-feira","Quarta-feira","Quinta-feira","Sexta-feira","Sábado"],dayNamesShort:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],dayNamesMin:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],weekHeader:"Sm",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("pt-br",{buttonText:{month:"Mês",week:"Semana",day:"Dia",list:"Compromissos"},allDayText:"dia inteiro",eventLimitText:function(e){return"mais +"+e},noEventsMessage:"Não há eventos para mostrar"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("pt-br",{months:"Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),weekdaysMin:"Do_2ª_3ª_4ª_5ª_6ª_Sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY [às] HH:mm",LLLL:"dddd, D [de] MMMM [de] YYYY [às] HH:mm"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){return 0===this.day()||6===this.day()?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"há %s",s:"poucos segundos",ss:"%d segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº"})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(186);var n=t(1);n.datepickerLocale("pt","pt",{closeText:"Fechar",prevText:"Anterior",nextText:"Seguinte",currentText:"Hoje",monthNames:["Janeiro","Fevereiro","Março","Abril","Maio","Junho","Julho","Agosto","Setembro","Outubro","Novembro","Dezembro"],monthNamesShort:["Jan","Fev","Mar","Abr","Mai","Jun","Jul","Ago","Set","Out","Nov","Dez"],dayNames:["Domingo","Segunda-feira","Terça-feira","Quarta-feira","Quinta-feira","Sexta-feira","Sábado"],dayNamesShort:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],dayNamesMin:["Dom","Seg","Ter","Qua","Qui","Sex","Sáb"],weekHeader:"Sem",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("pt",{buttonText:{month:"Mês",week:"Semana",day:"Dia",list:"Agenda"},allDayText:"Todo o dia",eventLimitText:"mais",noEventsMessage:"Não há eventos para mostrar"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("pt",{months:"Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),weekdaysMin:"Do_2ª_3ª_4ª_5ª_6ª_Sá".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY HH:mm",LLLL:"dddd, D [de] MMMM [de] YYYY HH:mm"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){return 0===this.day()||6===this.day()?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"há %s",s:"segundos",ss:"%d segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},dayOfMonthOrdinalParse:/\d{1,2}º/,ordinal:"%dº",week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(188);var n=t(1);n.datepickerLocale("ro","ro",{closeText:"Închide",prevText:"« Luna precedentă",nextText:"Luna următoare »",currentText:"Azi",monthNames:["Ianuarie","Februarie","Martie","Aprilie","Mai","Iunie","Iulie","August","Septembrie","Octombrie","Noiembrie","Decembrie"],monthNamesShort:["Ian","Feb","Mar","Apr","Mai","Iun","Iul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Duminică","Luni","Marţi","Miercuri","Joi","Vineri","Sâmbătă"],dayNamesShort:["Dum","Lun","Mar","Mie","Joi","Vin","Sâm"],dayNamesMin:["Du","Lu","Ma","Mi","Jo","Vi","Sâ"],weekHeader:"Săpt",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("ro",{buttonText:{prev:"precedentă",next:"următoare",month:"Lună",week:"Săptămână",day:"Zi",list:"Agendă"},allDayText:"Toată ziua",eventLimitText:function(e){return"+alte "+e},noEventsMessage:"Nu există evenimente de afișat"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){function a(e,a,t){var n={ss:"secunde",mm:"minute",hh:"ore",dd:"zile",MM:"luni",yy:"ani"},r=" ";return(e%100>=20||e>=100&&e%100==0)&&(r=" de "),e+r+n[t]}return e.defineLocale("ro",{months:"ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie".split("_"),monthsShort:"ian._febr._mart._apr._mai_iun._iul._aug._sept._oct._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"duminică_luni_marți_miercuri_joi_vineri_sâmbătă".split("_"),weekdaysShort:"Dum_Lun_Mar_Mie_Joi_Vin_Sâm".split("_"),weekdaysMin:"Du_Lu_Ma_Mi_Jo_Vi_Sâ".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[azi la] LT",nextDay:"[mâine la] LT",nextWeek:"dddd [la] LT",lastDay:"[ieri la] LT",lastWeek:"[fosta] dddd [la] LT",sameElse:"L"},relativeTime:{future:"peste %s",past:"%s în urmă",s:"câteva secunde",ss:a,m:"un minut",mm:a,h:"o oră",hh:a,d:"o zi",dd:a,M:"o lună",MM:a,y:"un an",yy:a},week:{dow:1,doy:7}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(190);var n=t(1);n.datepickerLocale("ru","ru",{closeText:"Закрыть",prevText:"<Пред",nextText:"След>",currentText:"Сегодня",monthNames:["Январь","Февраль","Март","Апрель","Май","Июнь","Июль","Август","Сентябрь","Октябрь","Ноябрь","Декабрь"],monthNamesShort:["Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек"],dayNames:["воскресенье","понедельник","вторник","среда","четверг","пятница","суббота"],dayNamesShort:["вск","пнд","втр","срд","чтв","птн","сбт"],dayNamesMin:["Вс","Пн","Вт","Ср","Чт","Пт","Сб"],weekHeader:"Нед",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("ru",{buttonText:{month:"Месяц",week:"Неделя",day:"День",list:"Повестка дня"},allDayText:"Весь день",eventLimitText:function(e){return"+ ещё "+e},noEventsMessage:"Нет событий для отображения"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){function a(e,a){var t=e.split("_");return a%10==1&&a%100!=11?t[0]:a%10>=2&&a%10<=4&&(a%100<10||a%100>=20)?t[1]:t[2]}function t(e,t,n){var r={ss:t?"секунда_секунды_секунд":"секунду_секунды_секунд",mm:t?"минута_минуты_минут":"минуту_минуты_минут",hh:"час_часа_часов",dd:"день_дня_дней",MM:"месяц_месяца_месяцев",yy:"год_года_лет"};return"m"===n?t?"минута":"минуту":e+" "+a(r[n],+e)}var n=[/^янв/i,/^фев/i,/^мар/i,/^апр/i,/^ма[йя]/i,/^июн/i,/^июл/i,/^авг/i,/^сен/i,/^окт/i,/^ноя/i,/^дек/i];return e.defineLocale("ru",{months:{format:"января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря".split("_"),standalone:"январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь".split("_")},monthsShort:{format:"янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.".split("_"),standalone:"янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.".split("_")},weekdays:{standalone:"воскресенье_понедельник_вторник_среда_четверг_пятница_суббота".split("_"),format:"воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу".split("_"),isFormat:/\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?\] ?dddd/},weekdaysShort:"вс_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"вс_пн_вт_ср_чт_пт_сб".split("_"),monthsParse:n,longMonthsParse:n,shortMonthsParse:n,monthsRegex:/^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i,monthsShortRegex:/^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i,monthsStrictRegex:/^(январ[яь]|феврал[яь]|марта?|апрел[яь]|ма[яй]|июн[яь]|июл[яь]|августа?|сентябр[яь]|октябр[яь]|ноябр[яь]|декабр[яь])/i,monthsShortStrictRegex:/^(янв\.|февр?\.|мар[т.]|апр\.|ма[яй]|июн[ья.]|июл[ья.]|авг\.|сент?\.|окт\.|нояб?\.|дек\.)/i,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY г.",LLL:"D MMMM YYYY г., H:mm",LLLL:"dddd, D MMMM YYYY г., H:mm"},calendar:{sameDay:"[Сегодня, в] LT",nextDay:"[Завтра, в] LT",lastDay:"[Вчера, в] LT",nextWeek:function(e){if(e.week()===this.week())return 2===this.day()?"[Во] dddd, [в] LT":"[В] dddd, [в] LT";switch(this.day()){case 0:return"[В следующее] dddd, [в] LT";case 1:case 2:case 4:return"[В следующий] dddd, [в] LT";case 3:case 5:case 6:return"[В следующую] dddd, [в] LT"}},lastWeek:function(e){if(e.week()===this.week())return 2===this.day()?"[Во] dddd, [в] LT":"[В] dddd, [в] LT";switch(this.day()){case 0:return"[В прошлое] dddd, [в] LT";case 1:case 2:case 4:return"[В прошлый] dddd, [в] LT";case 3:case 5:case 6:return"[В прошлую] dddd, [в] LT"}},sameElse:"L"},relativeTime:{future:"через %s",past:"%s назад",s:"несколько секунд",ss:t,m:t,mm:t,h:"час",hh:t,d:"день",dd:t,M:"месяц",MM:t,y:"год",yy:t},meridiemParse:/ночи|утра|дня|вечера/i,isPM:function(e){return/^(дня|вечера)$/.test(e)},meridiem:function(e,a,t){return e<4?"ночи":e<12?"утра":e<17?"дня":"вечера"},dayOfMonthOrdinalParse:/\d{1,2}-(й|го|я)/,ordinal:function(e,a){switch(a){case"M":case"d":case"DDD":return e+"-й";case"D":return e+"-го";case"w":case"W":return e+"-я";default:return e}},week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(192);var n=t(1);n.datepickerLocale("sk","sk",{closeText:"Zavrieť",prevText:"<Predchádzajúci",nextText:"Nasledujúci>",currentText:"Dnes",monthNames:["január","február","marec","apríl","máj","jún","júl","august","september","október","november","december"],monthNamesShort:["Jan","Feb","Mar","Apr","Máj","Jún","Júl","Aug","Sep","Okt","Nov","Dec"],dayNames:["nedeľa","pondelok","utorok","streda","štvrtok","piatok","sobota"],dayNamesShort:["Ned","Pon","Uto","Str","Štv","Pia","Sob"],dayNamesMin:["Ne","Po","Ut","St","Št","Pia","So"],weekHeader:"Ty",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("sk",{buttonText:{month:"Mesiac",week:"Týždeň",day:"Deň",list:"Rozvrh"},allDayText:"Celý deň",eventLimitText:function(e){return"+ďalšie: "+e},noEventsMessage:"Žiadne akcie na zobrazenie"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){function a(e){return e>1&&e<5}function t(e,t,n,r){var s=e+" ";switch(n){case"s":return t||r?"pár sekúnd":"pár sekundami";case"ss":return t||r?s+(a(e)?"sekundy":"sekúnd"):s+"sekundami";case"m":return t?"minúta":r?"minútu":"minútou";case"mm":return t||r?s+(a(e)?"minúty":"minút"):s+"minútami";case"h":return t?"hodina":r?"hodinu":"hodinou";case"hh":return t||r?s+(a(e)?"hodiny":"hodín"):s+"hodinami";case"d":return t||r?"deň":"dňom";case"dd":return t||r?s+(a(e)?"dni":"dní"):s+"dňami";case"M":return t||r?"mesiac":"mesiacom";case"MM":return t||r?s+(a(e)?"mesiace":"mesiacov"):s+"mesiacmi";case"y":return t||r?"rok":"rokom";case"yy":return t||r?s+(a(e)?"roky":"rokov"):s+"rokmi"}}var n="január_február_marec_apríl_máj_jún_júl_august_september_október_november_december".split("_"),r="jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec".split("_");return e.defineLocale("sk",{months:n,monthsShort:r,weekdays:"nedeľa_pondelok_utorok_streda_štvrtok_piatok_sobota".split("_"),weekdaysShort:"ne_po_ut_st_št_pi_so".split("_"),weekdaysMin:"ne_po_ut_st_št_pi_so".split("_"),longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd D. MMMM YYYY H:mm"},calendar:{sameDay:"[dnes o] LT",nextDay:"[zajtra o] LT",nextWeek:function(){switch(this.day()){case 0:return"[v nedeľu o] LT";case 1:case 2:return"[v] dddd [o] LT";case 3:return"[v stredu o] LT";case 4:return"[vo štvrtok o] LT";case 5:return"[v piatok o] LT";case 6:return"[v sobotu o] LT"}},lastDay:"[včera o] LT",lastWeek:function(){switch(this.day()){case 0:return"[minulú nedeľu o] LT";case 1:case 2:return"[minulý] dddd [o] LT";case 3:return"[minulú stredu o] LT";case 4:case 5:return"[minulý] dddd [o] LT";case 6:return"[minulú sobotu o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"pred %s",s:t,ss:t,m:t,mm:t,h:t,hh:t,d:t,dd:t,M:t,MM:t,y:t,yy:t},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(194);var n=t(1);n.datepickerLocale("sl","sl",{closeText:"Zapri",prevText:"<Prejšnji",nextText:"Naslednji>",currentText:"Trenutni",monthNames:["Januar","Februar","Marec","April","Maj","Junij","Julij","Avgust","September","Oktober","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],dayNames:["Nedelja","Ponedeljek","Torek","Sreda","Četrtek","Petek","Sobota"],dayNamesShort:["Ned","Pon","Tor","Sre","Čet","Pet","Sob"],dayNamesMin:["Ne","Po","To","Sr","Če","Pe","So"],weekHeader:"Teden",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("sl",{buttonText:{month:"Mesec",week:"Teden",day:"Dan",list:"Dnevni red"},allDayText:"Ves dan",eventLimitText:"več",noEventsMessage:"Ni dogodkov za prikaz"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){function a(e,a,t,n){var r=e+" ";switch(t){case"s":return a||n?"nekaj sekund":"nekaj sekundami";case"ss":return r+=1===e?a?"sekundo":"sekundi":2===e?a||n?"sekundi":"sekundah":e<5?a||n?"sekunde":"sekundah":"sekund";case"m":return a?"ena minuta":"eno minuto";case"mm":return r+=1===e?a?"minuta":"minuto":2===e?a||n?"minuti":"minutama":e<5?a||n?"minute":"minutami":a||n?"minut":"minutami";case"h":return a?"ena ura":"eno uro";case"hh":return r+=1===e?a?"ura":"uro":2===e?a||n?"uri":"urama":e<5?a||n?"ure":"urami":a||n?"ur":"urami";case"d":return a||n?"en dan":"enim dnem";case"dd":return r+=1===e?a||n?"dan":"dnem":2===e?a||n?"dni":"dnevoma":a||n?"dni":"dnevi";case"M":return a||n?"en mesec":"enim mesecem";case"MM":return r+=1===e?a||n?"mesec":"mesecem":2===e?a||n?"meseca":"mesecema":e<5?a||n?"mesece":"meseci":a||n?"mesecev":"meseci";case"y":return a||n?"eno leto":"enim letom";case"yy":return r+=1===e?a||n?"leto":"letom":2===e?a||n?"leti":"letoma":e<5?a||n?"leta":"leti":a||n?"let":"leti"}}return e.defineLocale("sl",{months:"januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december".split("_"),monthsShort:"jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota".split("_"),weekdaysShort:"ned._pon._tor._sre._čet._pet._sob.".split("_"),weekdaysMin:"ne_po_to_sr_če_pe_so".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danes ob] LT",nextDay:"[jutri ob] LT",nextWeek:function(){switch(this.day()){case 0:return"[v] [nedeljo] [ob] LT";case 3:return"[v] [sredo] [ob] LT";case 6:return"[v] [soboto] [ob] LT";case 1:case 2:case 4:case 5:return"[v] dddd [ob] LT"}},lastDay:"[včeraj ob] LT",lastWeek:function(){switch(this.day()){case 0:return"[prejšnjo] [nedeljo] [ob] LT";case 3:return"[prejšnjo] [sredo] [ob] LT";case 6:return"[prejšnjo] [soboto] [ob] LT";case 1:case 2:case 4:case 5:return"[prejšnji] dddd [ob] LT"}},sameElse:"L"},relativeTime:{future:"čez %s",past:"pred %s",s:a,ss:a,m:a,mm:a,h:a,hh:a,d:a,dd:a,M:a,MM:a,y:a,yy:a},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(196);var n=t(1);n.datepickerLocale("sq","sq",{closeText:"mbylle",prevText:"<mbrapa",nextText:"Përpara>",currentText:"sot",monthNames:["Janar","Shkurt","Mars","Prill","Maj","Qershor","Korrik","Gusht","Shtator","Tetor","Nëntor","Dhjetor"],monthNamesShort:["Jan","Shk","Mar","Pri","Maj","Qer","Kor","Gus","Sht","Tet","Nën","Dhj"],dayNames:["E Diel","E Hënë","E Martë","E Mërkurë","E Enjte","E Premte","E Shtune"],dayNamesShort:["Di","Hë","Ma","Më","En","Pr","Sh"],dayNamesMin:["Di","Hë","Ma","Më","En","Pr","Sh"],weekHeader:"Ja",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("sq",{buttonText:{month:"Muaj",week:"Javë",day:"Ditë",list:"Listë"},allDayHtml:"Gjithë
ditën",eventLimitText:function(e){return"+më tepër "+e},noEventsMessage:"Nuk ka evente për të shfaqur"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("sq",{months:"Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor".split("_"),monthsShort:"Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj".split("_"),weekdays:"E Diel_E Hënë_E Martë_E Mërkurë_E Enjte_E Premte_E Shtunë".split("_"),weekdaysShort:"Die_Hën_Mar_Mër_Enj_Pre_Sht".split("_"),weekdaysMin:"D_H_Ma_Më_E_P_Sh".split("_"),weekdaysParseExact:!0,meridiemParse:/PD|MD/,isPM:function(e){return"M"===e.charAt(0)},meridiem:function(e,a,t){return e<12?"PD":"MD"},longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[Sot në] LT",nextDay:"[Nesër në] LT",nextWeek:"dddd [në] LT",lastDay:"[Dje në] LT",lastWeek:"dddd [e kaluar në] LT",sameElse:"L"},relativeTime:{future:"në %s",past:"%s më parë",s:"disa sekonda",ss:"%d sekonda",m:"një minutë",mm:"%d minuta",h:"një orë",hh:"%d orë",d:"një ditë",dd:"%d ditë",M:"një muaj",MM:"%d muaj",y:"një vit",yy:"%d vite"},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(198);var n=t(1);n.datepickerLocale("sr-cyrl","sr",{closeText:"Затвори",prevText:"<",nextText:">",currentText:"Данас",monthNames:["Јануар","Фебруар","Март","Април","Мај","Јун","Јул","Август","Септембар","Октобар","Новембар","Децембар"],monthNamesShort:["Јан","Феб","Мар","Апр","Мај","Јун","Јул","Авг","Сеп","Окт","Нов","Дец"],dayNames:["Недеља","Понедељак","Уторак","Среда","Четвртак","Петак","Субота"],dayNamesShort:["Нед","Пон","Уто","Сре","Чет","Пет","Суб"],dayNamesMin:["Не","По","Ут","Ср","Че","Пе","Су"],weekHeader:"Сед",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("sr-cyrl",{buttonText:{prev:"Претходна",next:"следећи",month:"Месец",week:"Недеља",day:"Дан",list:"Планер"},allDayText:"Цео дан",eventLimitText:function(e){return"+ још "+e},noEventsMessage:"Нема догађаја за приказ"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){var a={words:{ss:["секунда","секунде","секунди"],m:["један минут","једне минуте"],mm:["минут","минуте","минута"],h:["један сат","једног сата"],hh:["сат","сата","сати"],dd:["дан","дана","дана"],MM:["месец","месеца","месеци"],yy:["година","године","година"]},correctGrammaticalCase:function(e,a){return 1===e?a[0]:e>=2&&e<=4?a[1]:a[2]},translate:function(e,t,n){var r=a.words[n];return 1===n.length?t?r[0]:r[1]:e+" "+a.correctGrammaticalCase(e,r)}};return e.defineLocale("sr-cyrl",{months:"јануар_фебруар_март_април_мај_јун_јул_август_септембар_октобар_новембар_децембар".split("_"),monthsShort:"јан._феб._мар._апр._мај_јун_јул_авг._сеп._окт._нов._дец.".split("_"),monthsParseExact:!0,weekdays:"недеља_понедељак_уторак_среда_четвртак_петак_субота".split("_"),weekdaysShort:"нед._пон._уто._сре._чет._пет._суб.".split("_"),weekdaysMin:"не_по_ут_ср_че_пе_су".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[данас у] LT",nextDay:"[сутра у] LT",nextWeek:function(){switch(this.day()){case 0:return"[у] [недељу] [у] LT";case 3:return"[у] [среду] [у] LT";case 6:return"[у] [суботу] [у] LT";case 1:case 2:case 4:case 5:return"[у] dddd [у] LT"}},lastDay:"[јуче у] LT",lastWeek:function(){return["[прошле] [недеље] [у] LT","[прошлог] [понедељка] [у] LT","[прошлог] [уторка] [у] LT","[прошле] [среде] [у] LT","[прошлог] [четвртка] [у] LT","[прошлог] [петка] [у] LT","[прошле] [суботе] [у] LT"][this.day()]},sameElse:"L"},relativeTime:{future:"за %s",past:"пре %s",s:"неколико секунди",ss:a.translate,m:a.translate,mm:a.translate,h:a.translate,hh:a.translate,d:"дан",dd:a.translate,M:"месец",MM:a.translate,y:"годину",yy:a.translate},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(200);var n=t(1);n.datepickerLocale("sr","sr-SR",{closeText:"Zatvori",prevText:"<",nextText:">",currentText:"Danas",monthNames:["Januar","Februar","Mart","April","Maj","Jun","Jul","Avgust","Septembar","Oktobar","Novembar","Decembar"],monthNamesShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Avg","Sep","Okt","Nov","Dec"],dayNames:["Nedelja","Ponedeljak","Utorak","Sreda","Četvrtak","Petak","Subota"],dayNamesShort:["Ned","Pon","Uto","Sre","Čet","Pet","Sub"],dayNamesMin:["Ne","Po","Ut","Sr","Če","Pe","Su"],weekHeader:"Sed",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("sr",{buttonText:{prev:"Prethodna",next:"Sledeći",month:"Mеsеc",week:"Nеdеlja",day:"Dan",list:"Planеr"},allDayText:"Cеo dan",eventLimitText:function(e){return"+ još "+e},noEventsMessage:"Nеma događaja za prikaz"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){var a={words:{ss:["sekunda","sekunde","sekundi"],m:["jedan minut","jedne minute"],mm:["minut","minute","minuta"],h:["jedan sat","jednog sata"],hh:["sat","sata","sati"],dd:["dan","dana","dana"],MM:["mesec","meseca","meseci"],yy:["godina","godine","godina"]},correctGrammaticalCase:function(e,a){return 1===e?a[0]:e>=2&&e<=4?a[1]:a[2]},translate:function(e,t,n){var r=a.words[n];return 1===n.length?t?r[0]:r[1]:e+" "+a.correctGrammaticalCase(e,r)}};return e.defineLocale("sr",{months:"januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.".split("_"),monthsParseExact:!0,weekdays:"nedelja_ponedeljak_utorak_sreda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sre._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY H:mm",LLLL:"dddd, D. MMMM YYYY H:mm"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedelju] [u] LT";case 3:return"[u] [sredu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[juče u] LT",lastWeek:function(){return["[prošle] [nedelje] [u] LT","[prošlog] [ponedeljka] [u] LT","[prošlog] [utorka] [u] LT","[prošle] [srede] [u] LT","[prošlog] [četvrtka] [u] LT","[prošlog] [petka] [u] LT","[prošle] [subote] [u] LT"][this.day()]},sameElse:"L"},relativeTime:{future:"za %s",past:"pre %s",s:"nekoliko sekundi",ss:a.translate,m:a.translate,mm:a.translate,h:a.translate,hh:a.translate,d:"dan",dd:a.translate,M:"mesec",MM:a.translate,y:"godinu",yy:a.translate},dayOfMonthOrdinalParse:/\d{1,2}\./,ordinal:"%d.",week:{dow:1,doy:7}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(202);var n=t(1);n.datepickerLocale("sv","sv",{closeText:"Stäng",prevText:"«Förra",nextText:"Nästa»",currentText:"Idag",monthNames:["Januari","Februari","Mars","April","Maj","Juni","Juli","Augusti","September","Oktober","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],dayNamesShort:["Sön","Mån","Tis","Ons","Tor","Fre","Lör"],dayNames:["Söndag","Måndag","Tisdag","Onsdag","Torsdag","Fredag","Lördag"],dayNamesMin:["Sö","Må","Ti","On","To","Fr","Lö"],weekHeader:"v. ",dateFormat:"yy-mm-dd",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("sv",{buttonText:{month:"Månad",week:"Vecka",day:"Dag",list:"Program"},allDayText:"Heldag",eventLimitText:"till",noEventsMessage:"Inga händelser att visa"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("sv",{months:"januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag".split("_"),weekdaysShort:"sön_mån_tis_ons_tor_fre_lör".split("_"),weekdaysMin:"sö_må_ti_on_to_fr_lö".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [kl.] HH:mm",LLLL:"dddd D MMMM YYYY [kl.] HH:mm",lll:"D MMM YYYY HH:mm",llll:"ddd D MMM YYYY HH:mm"},calendar:{sameDay:"[Idag] LT",nextDay:"[Imorgon] LT",lastDay:"[Igår] LT",nextWeek:"[På] dddd LT",lastWeek:"[I] dddd[s] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"för %s sedan",s:"några sekunder",ss:"%d sekunder",m:"en minut",mm:"%d minuter",h:"en timme",hh:"%d timmar",d:"en dag",dd:"%d dagar",M:"en månad",MM:"%d månader",y:"ett år",yy:"%d år"},dayOfMonthOrdinalParse:/\d{1,2}(e|a)/,ordinal:function(e){var a=e%10;return e+(1==~~(e%100/10)?"e":1===a?"a":2===a?"a":"e")},week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(204);var n=t(1);n.datepickerLocale("th","th",{closeText:"ปิด",prevText:"« ย้อน",nextText:"ถัดไป »",currentText:"วันนี้",monthNames:["มกราคม","กุมภาพันธ์","มีนาคม","เมษายน","พฤษภาคม","มิถุนายน","กรกฎาคม","สิงหาคม","กันยายน","ตุลาคม","พฤศจิกายน","ธันวาคม"],monthNamesShort:["ม.ค.","ก.พ.","มี.ค.","เม.ย.","พ.ค.","มิ.ย.","ก.ค.","ส.ค.","ก.ย.","ต.ค.","พ.ย.","ธ.ค."],dayNames:["อาทิตย์","จันทร์","อังคาร","พุธ","พฤหัสบดี","ศุกร์","เสาร์"],dayNamesShort:["อา.","จ.","อ.","พ.","พฤ.","ศ.","ส."],dayNamesMin:["อา.","จ.","อ.","พ.","พฤ.","ศ.","ส."],weekHeader:"Wk",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("th",{buttonText:{month:"เดือน",week:"สัปดาห์",day:"วัน",list:"แผนงาน"},allDayText:"ตลอดวัน",eventLimitText:"เพิ่มเติม",noEventsMessage:"ไม่มีกิจกรรมที่จะแสดง"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("th",{months:"มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม".split("_"),monthsShort:"ม.ค._ก.พ._มี.ค._เม.ย._พ.ค._มิ.ย._ก.ค._ส.ค._ก.ย._ต.ค._พ.ย._ธ.ค.".split("_"),monthsParseExact:!0,weekdays:"อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์".split("_"),weekdaysShort:"อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์".split("_"),weekdaysMin:"อา._จ._อ._พ._พฤ._ศ._ส.".split("_"),weekdaysParseExact:!0,longDateFormat:{LT:"H:mm",LTS:"H:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY เวลา H:mm",LLLL:"วันddddที่ D MMMM YYYY เวลา H:mm"},meridiemParse:/ก่อนเที่ยง|หลังเที่ยง/,isPM:function(e){return"หลังเที่ยง"===e},meridiem:function(e,a,t){return e<12?"ก่อนเที่ยง":"หลังเที่ยง"},calendar:{sameDay:"[วันนี้ เวลา] LT",nextDay:"[พรุ่งนี้ เวลา] LT",nextWeek:"dddd[หน้า เวลา] LT",lastDay:"[เมื่อวานนี้ เวลา] LT",lastWeek:"[วัน]dddd[ที่แล้ว เวลา] LT",sameElse:"L"},relativeTime:{future:"อีก %s",past:"%sที่แล้ว",s:"ไม่กี่วินาที",ss:"%d วินาที",m:"1 นาที",mm:"%d นาที",h:"1 ชั่วโมง",hh:"%d ชั่วโมง",d:"1 วัน",dd:"%d วัน",M:"1 เดือน",MM:"%d เดือน",y:"1 ปี",yy:"%d ปี"}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(206);var n=t(1);n.datepickerLocale("tr","tr",{closeText:"kapat",prevText:"<geri",nextText:"ileri>",currentText:"bugün",monthNames:["Ocak","Şubat","Mart","Nisan","Mayıs","Haziran","Temmuz","Ağustos","Eylül","Ekim","Kasım","Aralık"],monthNamesShort:["Oca","Şub","Mar","Nis","May","Haz","Tem","Ağu","Eyl","Eki","Kas","Ara"],dayNames:["Pazar","Pazartesi","Salı","Çarşamba","Perşembe","Cuma","Cumartesi"],dayNamesShort:["Pz","Pt","Sa","Ça","Pe","Cu","Ct"],dayNamesMin:["Pz","Pt","Sa","Ça","Pe","Cu","Ct"],weekHeader:"Hf",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("tr",{buttonText:{next:"ileri",month:"Ay",week:"Hafta",day:"Gün",list:"Ajanda"},allDayText:"Tüm gün",eventLimitText:"daha fazla",noEventsMessage:"Gösterilecek etkinlik yok"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){var a={1:"'inci",5:"'inci",8:"'inci",70:"'inci",80:"'inci",2:"'nci",7:"'nci",20:"'nci",50:"'nci",3:"'üncü",4:"'üncü",100:"'üncü",6:"'ncı",9:"'uncu",10:"'uncu",30:"'uncu",60:"'ıncı",90:"'ıncı"};return e.defineLocale("tr",{months:"Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık".split("_"), +monthsShort:"Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara".split("_"),weekdays:"Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi".split("_"),weekdaysShort:"Paz_Pts_Sal_Çar_Per_Cum_Cts".split("_"),weekdaysMin:"Pz_Pt_Sa_Ça_Pe_Cu_Ct".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY HH:mm",LLLL:"dddd, D MMMM YYYY HH:mm"},calendar:{sameDay:"[bugün saat] LT",nextDay:"[yarın saat] LT",nextWeek:"[gelecek] dddd [saat] LT",lastDay:"[dün] LT",lastWeek:"[geçen] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s sonra",past:"%s önce",s:"birkaç saniye",ss:"%d saniye",m:"bir dakika",mm:"%d dakika",h:"bir saat",hh:"%d saat",d:"bir gün",dd:"%d gün",M:"bir ay",MM:"%d ay",y:"bir yıl",yy:"%d yıl"},ordinal:function(e,t){switch(t){case"d":case"D":case"Do":case"DD":return e;default:if(0===e)return e+"'ıncı";var n=e%10,r=e%100-n,s=e>=100?100:null;return e+(a[n]||a[r]||a[s])}},week:{dow:1,doy:7}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(208);var n=t(1);n.datepickerLocale("uk","uk",{closeText:"Закрити",prevText:"<",nextText:">",currentText:"Сьогодні",monthNames:["Січень","Лютий","Березень","Квітень","Травень","Червень","Липень","Серпень","Вересень","Жовтень","Листопад","Грудень"],monthNamesShort:["Січ","Лют","Бер","Кві","Тра","Чер","Лип","Сер","Вер","Жов","Лис","Гру"],dayNames:["неділя","понеділок","вівторок","середа","четвер","п’ятниця","субота"],dayNamesShort:["нед","пнд","вів","срд","чтв","птн","сбт"],dayNamesMin:["Нд","Пн","Вт","Ср","Чт","Пт","Сб"],weekHeader:"Тиж",dateFormat:"dd.mm.yy",firstDay:1,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("uk",{buttonText:{month:"Місяць",week:"Тиждень",day:"День",list:"Порядок денний"},allDayText:"Увесь день",eventLimitText:function(e){return"+ще "+e+"..."},noEventsMessage:"Немає подій для відображення"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){function a(e,a){var t=e.split("_");return a%10==1&&a%100!=11?t[0]:a%10>=2&&a%10<=4&&(a%100<10||a%100>=20)?t[1]:t[2]}function t(e,t,n){var r={ss:t?"секунда_секунди_секунд":"секунду_секунди_секунд",mm:t?"хвилина_хвилини_хвилин":"хвилину_хвилини_хвилин",hh:t?"година_години_годин":"годину_години_годин",dd:"день_дні_днів",MM:"місяць_місяці_місяців",yy:"рік_роки_років"};return"m"===n?t?"хвилина":"хвилину":"h"===n?t?"година":"годину":e+" "+a(r[n],+e)}function n(e,a){var t={nominative:"неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота".split("_"),accusative:"неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу".split("_"),genitive:"неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи".split("_")};return!0===e?t.nominative.slice(1,7).concat(t.nominative.slice(0,1)):e?t[/(\[[ВвУу]\]) ?dddd/.test(a)?"accusative":/\[?(?:минулої|наступної)? ?\] ?dddd/.test(a)?"genitive":"nominative"][e.day()]:t.nominative}function r(e){return function(){return e+"о"+(11===this.hours()?"б":"")+"] LT"}}return e.defineLocale("uk",{months:{format:"січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня".split("_"),standalone:"січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень".split("_")},monthsShort:"січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд".split("_"),weekdays:n,weekdaysShort:"нд_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD.MM.YYYY",LL:"D MMMM YYYY р.",LLL:"D MMMM YYYY р., HH:mm",LLLL:"dddd, D MMMM YYYY р., HH:mm"},calendar:{sameDay:r("[Сьогодні "),nextDay:r("[Завтра "),lastDay:r("[Вчора "),nextWeek:r("[У] dddd ["),lastWeek:function(){switch(this.day()){case 0:case 3:case 5:case 6:return r("[Минулої] dddd [").call(this);case 1:case 2:case 4:return r("[Минулого] dddd [").call(this)}},sameElse:"L"},relativeTime:{future:"за %s",past:"%s тому",s:"декілька секунд",ss:t,m:t,mm:t,h:"годину",hh:t,d:"день",dd:t,M:"місяць",MM:t,y:"рік",yy:t},meridiemParse:/ночі|ранку|дня|вечора/,isPM:function(e){return/^(дня|вечора)$/.test(e)},meridiem:function(e,a,t){return e<4?"ночі":e<12?"ранку":e<17?"дня":"вечора"},dayOfMonthOrdinalParse:/\d{1,2}-(й|го)/,ordinal:function(e,a){switch(a){case"M":case"d":case"DDD":case"w":case"W":return e+"-й";case"D":return e+"-го";default:return e}},week:{dow:1,doy:7}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(210);var n=t(1);n.datepickerLocale("vi","vi",{closeText:"Đóng",prevText:"<Trước",nextText:"Tiếp>",currentText:"Hôm nay",monthNames:["Tháng Một","Tháng Hai","Tháng Ba","Tháng Tư","Tháng Năm","Tháng Sáu","Tháng Bảy","Tháng Tám","Tháng Chín","Tháng Mười","Tháng Mười Một","Tháng Mười Hai"],monthNamesShort:["Tháng 1","Tháng 2","Tháng 3","Tháng 4","Tháng 5","Tháng 6","Tháng 7","Tháng 8","Tháng 9","Tháng 10","Tháng 11","Tháng 12"],dayNames:["Chủ Nhật","Thứ Hai","Thứ Ba","Thứ Tư","Thứ Năm","Thứ Sáu","Thứ Bảy"],dayNamesShort:["CN","T2","T3","T4","T5","T6","T7"],dayNamesMin:["CN","T2","T3","T4","T5","T6","T7"],weekHeader:"Tu",dateFormat:"dd/mm/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""}),n.locale("vi",{buttonText:{month:"Tháng",week:"Tuần",day:"Ngày",list:"Lịch biểu"},allDayText:"Cả ngày",eventLimitText:function(e){return"+ thêm "+e},noEventsMessage:"Không có sự kiện để hiển thị"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("vi",{months:"tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12".split("_"),monthsShort:"Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12".split("_"),monthsParseExact:!0,weekdays:"chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy".split("_"),weekdaysShort:"CN_T2_T3_T4_T5_T6_T7".split("_"),weekdaysMin:"CN_T2_T3_T4_T5_T6_T7".split("_"),weekdaysParseExact:!0,meridiemParse:/sa|ch/i,isPM:function(e){return/^ch$/i.test(e)},meridiem:function(e,a,t){return e<12?t?"sa":"SA":t?"ch":"CH"},longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM [năm] YYYY",LLL:"D MMMM [năm] YYYY HH:mm",LLLL:"dddd, D MMMM [năm] YYYY HH:mm",l:"DD/M/YYYY",ll:"D MMM YYYY",lll:"D MMM YYYY HH:mm",llll:"ddd, D MMM YYYY HH:mm"},calendar:{sameDay:"[Hôm nay lúc] LT",nextDay:"[Ngày mai lúc] LT",nextWeek:"dddd [tuần tới lúc] LT",lastDay:"[Hôm qua lúc] LT",lastWeek:"dddd [tuần rồi lúc] LT",sameElse:"L"},relativeTime:{future:"%s tới",past:"%s trước",s:"vài giây",ss:"%d giây",m:"một phút",mm:"%d phút",h:"một giờ",hh:"%d giờ",d:"một ngày",dd:"%d ngày",M:"một tháng",MM:"%d tháng",y:"một năm",yy:"%d năm"},dayOfMonthOrdinalParse:/\d{1,2}/,ordinal:function(e){return e},week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(212);var n=t(1);n.datepickerLocale("zh-cn","zh-CN",{closeText:"关闭",prevText:"<上月",nextText:"下月>",currentText:"今天",monthNames:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthNamesShort:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],dayNames:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],dayNamesShort:["周日","周一","周二","周三","周四","周五","周六"],dayNamesMin:["日","一","二","三","四","五","六"],weekHeader:"周",dateFormat:"yy-mm-dd",firstDay:1,isRTL:!1,showMonthAfterYear:!0,yearSuffix:"年"}),n.locale("zh-cn",{buttonText:{month:"月",week:"周",day:"日",list:"日程"},allDayText:"全天",eventLimitText:function(e){return"另外 "+e+" 个"},noEventsMessage:"没有事件显示"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("zh-cn",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"周日_周一_周二_周三_周四_周五_周六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日Ah点mm分",LLLL:"YYYY年M月D日ddddAh点mm分",l:"YYYY/M/D",ll:"YYYY年M月D日",lll:"YYYY年M月D日 HH:mm",llll:"YYYY年M月D日dddd HH:mm"},meridiemParse:/凌晨|早上|上午|中午|下午|晚上/,meridiemHour:function(e,a){return 12===e&&(e=0),"凌晨"===a||"早上"===a||"上午"===a?e:"下午"===a||"晚上"===a?e+12:e>=11?e:e+12},meridiem:function(e,a,t){var n=100*e+a;return n<600?"凌晨":n<900?"早上":n<1130?"上午":n<1230?"中午":n<1800?"下午":"晚上"},calendar:{sameDay:"[今天]LT",nextDay:"[明天]LT",nextWeek:"[下]ddddLT",lastDay:"[昨天]LT",lastWeek:"[上]ddddLT",sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}(日|月|周)/,ordinal:function(e,a){switch(a){case"d":case"D":case"DDD":return e+"日";case"M":return e+"月";case"w":case"W":return e+"周";default:return e}},relativeTime:{future:"%s内",past:"%s前",s:"几秒",ss:"%d 秒",m:"1 分钟",mm:"%d 分钟",h:"1 小时",hh:"%d 小时",d:"1 天",dd:"%d 天",M:"1 个月",MM:"%d 个月",y:"1 年",yy:"%d 年"},week:{dow:1,doy:4}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(214);var n=t(1);n.datepickerLocale("zh-hk","zh-HK",{closeText:"關閉",prevText:"<上月",nextText:"下月>",currentText:"今天",monthNames:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthNamesShort:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],dayNames:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],dayNamesShort:["周日","周一","周二","周三","周四","周五","周六"],dayNamesMin:["日","一","二","三","四","五","六"],weekHeader:"周",dateFormat:"yy/mm/dd",firstDay:1,isRTL:!1,showMonthAfterYear:!0,yearSuffix:"年"}),n.locale("zh-hk",{buttonText:{month:"月",week:"週",day:"天",list:"活動列表"},allDayText:"整天",eventLimitText:"顯示更多",noEventsMessage:"没有任何活動"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("zh-hk",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"週日_週一_週二_週三_週四_週五_週六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日 HH:mm",LLLL:"YYYY年M月D日dddd HH:mm",l:"YYYY/M/D",ll:"YYYY年M月D日",lll:"YYYY年M月D日 HH:mm",llll:"YYYY年M月D日dddd HH:mm"},meridiemParse:/凌晨|早上|上午|中午|下午|晚上/,meridiemHour:function(e,a){return 12===e&&(e=0),"凌晨"===a||"早上"===a||"上午"===a?e:"中午"===a?e>=11?e:e+12:"下午"===a||"晚上"===a?e+12:void 0},meridiem:function(e,a,t){var n=100*e+a;return n<600?"凌晨":n<900?"早上":n<1130?"上午":n<1230?"中午":n<1800?"下午":"晚上"},calendar:{sameDay:"[今天]LT",nextDay:"[明天]LT",nextWeek:"[下]ddddLT",lastDay:"[昨天]LT",lastWeek:"[上]ddddLT",sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}(日|月|週)/,ordinal:function(e,a){switch(a){case"d":case"D":case"DDD":return e+"日";case"M":return e+"月";case"w":case"W":return e+"週";default:return e}},relativeTime:{future:"%s內",past:"%s前",s:"幾秒",ss:"%d 秒",m:"1 分鐘",mm:"%d 分鐘",h:"1 小時",hh:"%d 小時",d:"1 天",dd:"%d 天",M:"1 個月",MM:"%d 個月",y:"1 年",yy:"%d 年"}})})},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0}),t(216);var n=t(1);n.datepickerLocale("zh-tw","zh-TW",{closeText:"關閉",prevText:"<上月",nextText:"下月>",currentText:"今天",monthNames:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],monthNamesShort:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"],dayNames:["星期日","星期一","星期二","星期三","星期四","星期五","星期六"],dayNamesShort:["周日","周一","周二","周三","周四","周五","周六"],dayNamesMin:["日","一","二","三","四","五","六"],weekHeader:"周",dateFormat:"yy/mm/dd",firstDay:1,isRTL:!1,showMonthAfterYear:!0,yearSuffix:"年"}),n.locale("zh-tw",{buttonText:{month:"月",week:"週",day:"天",list:"活動列表"},allDayText:"整天",eventLimitText:"顯示更多",noEventsMessage:"没有任何活動"})},function(e,a,t){!function(e,a){a(t(0))}(0,function(e){return e.defineLocale("zh-tw",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"週日_週一_週二_週三_週四_週五_週六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日 HH:mm",LLLL:"YYYY年M月D日dddd HH:mm",l:"YYYY/M/D",ll:"YYYY年M月D日",lll:"YYYY年M月D日 HH:mm",llll:"YYYY年M月D日dddd HH:mm"},meridiemParse:/凌晨|早上|上午|中午|下午|晚上/,meridiemHour:function(e,a){return 12===e&&(e=0),"凌晨"===a||"早上"===a||"上午"===a?e:"中午"===a?e>=11?e:e+12:"下午"===a||"晚上"===a?e+12:void 0},meridiem:function(e,a,t){var n=100*e+a;return n<600?"凌晨":n<900?"早上":n<1130?"上午":n<1230?"中午":n<1800?"下午":"晚上"},calendar:{sameDay:"[今天] LT",nextDay:"[明天] LT",nextWeek:"[下]dddd LT",lastDay:"[昨天] LT",lastWeek:"[上]dddd LT",sameElse:"L"},dayOfMonthOrdinalParse:/\d{1,2}(日|月|週)/,ordinal:function(e,a){switch(a){case"d":case"D":case"DDD":return e+"日";case"M":return e+"月";case"w":case"W":return e+"週";default:return e}},relativeTime:{future:"%s內",past:"%s前",s:"幾秒",ss:"%d 秒",m:"1 分鐘",mm:"%d 分鐘",h:"1 小時",hh:"%d 小時",d:"1 天",dd:"%d 天",M:"1 個月",MM:"%d 個月",y:"1 年",yy:"%d 年"}})})},,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,function(e,a,t){t(71),t(73),t(75),t(77),t(79),t(81),t(83),t(85),t(87),t(89),t(91),t(93),t(95),t(97),t(99),t(101),t(103),t(105),t(107),t(109),t(111),t(113),t(115),t(117),t(119),t(121),t(123),t(125),t(127),t(129),t(131),t(133),t(135),t(137),t(139),t(141),t(143),t(145),t(147),t(149),t(151),t(153),t(155),t(157),t(159),t(161),t(163),t(165),t(167),t(169),t(171),t(173),t(175),t(177),t(179),t(181),t(183),t(185),t(187),t(189),t(191),t(193),t(195),t(197),t(199),t(201),t(203),t(205),t(207),t(209),t(211),t(213),t(215),e.exports=t(439)},function(e,a,t){Object.defineProperty(a,"__esModule",{value:!0});var n=t(0),r=t(1);n.locale("en"),r.locale("en"),window.jQuery.datepicker&&window.jQuery.datepicker.setDefaults(window.jQuery.datepicker.regional[""])}])}); \ No newline at end of file diff --git a/src/assets/ext/jquery-jeditable/jquery.jeditable.min.js b/assets/ext/jquery-jeditable/jquery.jeditable.min.js similarity index 100% rename from src/assets/ext/jquery-jeditable/jquery.jeditable.min.js rename to assets/ext/jquery-jeditable/jquery.jeditable.min.js diff --git a/assets/ext/jquery-qtip/jquery.qtip.min.css b/assets/ext/jquery-qtip/jquery.qtip.min.css new file mode 100644 index 00000000..5adc4b75 --- /dev/null +++ b/assets/ext/jquery-qtip/jquery.qtip.min.css @@ -0,0 +1 @@ +#qtip-overlay.blurs,.qtip-close{cursor:pointer}.qtip{position:absolute;left:-28000px;top:-28000px;display:none;max-width:280px;min-width:50px;font-size:10.5px;line-height:12px;direction:ltr;box-shadow:none;padding:0}.qtip-content,.qtip-titlebar{position:relative;overflow:hidden}.qtip-content{padding:5px 9px;text-align:left;word-wrap:break-word}.qtip-titlebar{padding:5px 35px 5px 10px;border-width:0 0 1px;font-weight:700}.qtip-titlebar+.qtip-content{border-top-width:0!important}.qtip-close{position:absolute;right:-9px;top:-9px;z-index:11;outline:0;border:1px solid transparent}.qtip-titlebar .qtip-close{right:4px;top:50%;margin-top:-9px}* html .qtip-titlebar .qtip-close{top:16px}.qtip-icon .ui-icon,.qtip-titlebar .ui-icon{display:block;text-indent:-1000em;direction:ltr}.qtip-icon,.qtip-icon .ui-icon{-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;text-decoration:none}.qtip-icon .ui-icon{width:18px;height:14px;line-height:14px;text-align:center;text-indent:0;font:normal 700 10px/13px Tahoma,sans-serif;color:inherit;background:-100em -100em no-repeat}.qtip-default{border:1px solid #F1D031;background-color:#FFFFA3;color:#555}.qtip-default .qtip-titlebar{background-color:#FFEF93}.qtip-default .qtip-icon{border-color:#CCC;background:#F1F1F1;color:#777}.qtip-default .qtip-titlebar .qtip-close{border-color:#AAA;color:#111}.qtip-light{background-color:#fff;border-color:#E2E2E2;color:#454545}.qtip-light .qtip-titlebar{background-color:#f1f1f1}.qtip-dark{background-color:#505050;border-color:#303030;color:#f3f3f3}.qtip-dark .qtip-titlebar{background-color:#404040}.qtip-dark .qtip-icon{border-color:#444}.qtip-dark .qtip-titlebar .ui-state-hover{border-color:#303030}.qtip-cream{background-color:#FBF7AA;border-color:#F9E98E;color:#A27D35}.qtip-red,.qtip-red .qtip-icon,.qtip-red .qtip-titlebar .ui-state-hover{border-color:#D95252}.qtip-cream .qtip-titlebar{background-color:#F0DE7D}.qtip-cream .qtip-close .qtip-icon{background-position:-82px 0}.qtip-red{background-color:#F78B83;color:#912323}.qtip-red .qtip-titlebar{background-color:#F06D65}.qtip-red .qtip-close .qtip-icon{background-position:-102px 0}.qtip-green{background-color:#CAED9E;border-color:#90D93F;color:#3F6219}.qtip-green .qtip-titlebar{background-color:#B0DE78}.qtip-green .qtip-close .qtip-icon{background-position:-42px 0}.qtip-blue{background-color:#E5F6FE;border-color:#ADD9ED;color:#5E99BD}.qtip-blue .qtip-titlebar{background-color:#D0E9F5}.qtip-blue .qtip-close .qtip-icon{background-position:-2px 0}.qtip-shadow{-webkit-box-shadow:1px 1px 3px 1px rgba(0,0,0,.15);-moz-box-shadow:1px 1px 3px 1px rgba(0,0,0,.15);box-shadow:1px 1px 3px 1px rgba(0,0,0,.15)}.qtip-bootstrap,.qtip-rounded,.qtip-tipsy{-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.qtip-rounded .qtip-titlebar{-moz-border-radius:4px 4px 0 0;-webkit-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.qtip-youtube{-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-webkit-box-shadow:0 0 3px #333;-moz-box-shadow:0 0 3px #333;box-shadow:0 0 3px #333;color:#fff;border:0 solid transparent;background:#4A4A4A;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#4A4A4A),color-stop(100%,#000));background-image:-webkit-linear-gradient(top,#4A4A4A 0,#000 100%);background-image:-moz-linear-gradient(top,#4A4A4A 0,#000 100%);background-image:-ms-linear-gradient(top,#4A4A4A 0,#000 100%);background-image:-o-linear-gradient(top,#4A4A4A 0,#000 100%)}.qtip-youtube .qtip-titlebar{background-color:#4A4A4A;background-color:rgba(0,0,0,0)}.qtip-youtube .qtip-content{padding:.75em;font:12px arial,sans-serif;filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr=#4a4a4a, EndColorStr=#000000);-ms-filter:"progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr=#4a4a4a,EndColorStr=#000000);"}.qtip-youtube .qtip-icon{border-color:#222}.qtip-youtube .qtip-titlebar .ui-state-hover{border-color:#303030}.qtip-jtools{background:#232323;background:rgba(0,0,0,.7);background-image:-webkit-gradient(linear,left top,left bottom,from(#717171),to(#232323));background-image:-moz-linear-gradient(top,#717171,#232323);background-image:-webkit-linear-gradient(top,#717171,#232323);background-image:-ms-linear-gradient(top,#717171,#232323);background-image:-o-linear-gradient(top,#717171,#232323);border:2px solid #ddd;border:2px solid rgba(241,241,241,1);-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-webkit-box-shadow:0 0 12px #333;-moz-box-shadow:0 0 12px #333;box-shadow:0 0 12px #333}.qtip-jtools .qtip-titlebar{background-color:transparent;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171, endColorstr=#4A4A4A);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A)"}.qtip-jtools .qtip-content{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A, endColorstr=#232323);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323)"}.qtip-jtools .qtip-content,.qtip-jtools .qtip-titlebar{background:0 0;color:#fff;border:0 dashed transparent}.qtip-jtools .qtip-icon{border-color:#555}.qtip-jtools .qtip-titlebar .ui-state-hover{border-color:#333}.qtip-cluetip{-webkit-box-shadow:4px 4px 5px rgba(0,0,0,.4);-moz-box-shadow:4px 4px 5px rgba(0,0,0,.4);box-shadow:4px 4px 5px rgba(0,0,0,.4);background-color:#D9D9C2;color:#111;border:0 dashed transparent}.qtip-cluetip .qtip-titlebar{background-color:#87876A;color:#fff;border:0 dashed transparent}.qtip-cluetip .qtip-icon{border-color:#808064}.qtip-cluetip .qtip-titlebar .ui-state-hover{border-color:#696952;color:#696952}.qtip-tipsy{background:#000;background:rgba(0,0,0,.87);color:#fff;border:0 solid transparent;font-size:11px;font-family:'Lucida Grande',sans-serif;font-weight:700;line-height:16px;text-shadow:0 1px #000}.qtip-tipsy .qtip-titlebar{padding:6px 35px 0 10px;background-color:transparent}.qtip-tipsy .qtip-content{padding:6px 10px}.qtip-tipsy .qtip-icon{border-color:#222;text-shadow:none}.qtip-tipsy .qtip-titlebar .ui-state-hover{border-color:#303030}.qtip-tipped{border:3px solid #959FA9;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;background-color:#F9F9F9;color:#454545;font-weight:400;font-family:serif}.qtip-tipped .qtip-titlebar{border-bottom-width:0;color:#fff;background:#3A79B8;background-image:-webkit-gradient(linear,left top,left bottom,from(#3A79B8),to(#2E629D));background-image:-webkit-linear-gradient(top,#3A79B8,#2E629D);background-image:-moz-linear-gradient(top,#3A79B8,#2E629D);background-image:-ms-linear-gradient(top,#3A79B8,#2E629D);background-image:-o-linear-gradient(top,#3A79B8,#2E629D);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8, endColorstr=#2E629D);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D)"}.qtip-tipped .qtip-icon{border:2px solid #285589;background:#285589}.qtip-tipped .qtip-icon .ui-icon{background-color:#FBFBFB;color:#555}.qtip-bootstrap{font-size:14px;line-height:20px;color:#333;padding:1px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.qtip-bootstrap .qtip-titlebar{padding:8px 14px;margin:0;font-size:14px;font-weight:400;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.qtip-bootstrap .qtip-titlebar .qtip-close{right:11px;top:45%;border-style:none}.qtip-bootstrap .qtip-content{padding:9px 14px}.qtip-bootstrap .qtip-icon{background:0 0}.qtip-bootstrap .qtip-icon .ui-icon{width:auto;height:auto;float:right;font-size:20px;font-weight:700;line-height:18px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}#qtip-overlay,#qtip-overlay div{left:0;top:0;width:100%;height:100%}.qtip-bootstrap .qtip-icon .ui-icon:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}.qtip:not(.ie9haxors) div.qtip-content,.qtip:not(.ie9haxors) div.qtip-titlebar{filter:none;-ms-filter:none}.qtip .qtip-tip{margin:0 auto;overflow:hidden;z-index:10}.qtip .qtip-tip,x:-o-prefocus{visibility:hidden}.qtip .qtip-tip,.qtip .qtip-tip .qtip-vml,.qtip .qtip-tip canvas{position:absolute;color:#123456;background:0 0;border:0 dashed transparent}.qtip .qtip-tip canvas{top:0;left:0}.qtip .qtip-tip .qtip-vml{behavior:url(#default#VML);display:inline-block;visibility:visible}#qtip-overlay{position:fixed}#qtip-overlay div{position:absolute;background-color:#000;opacity:.7;filter:alpha(opacity=70);-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)"}.qtipmodal-ie6fix{position:absolute!important} \ No newline at end of file diff --git a/assets/ext/jquery-qtip/jquery.qtip.min.js b/assets/ext/jquery-qtip/jquery.qtip.min.js new file mode 100644 index 00000000..d2f28c56 --- /dev/null +++ b/assets/ext/jquery-qtip/jquery.qtip.min.js @@ -0,0 +1,5 @@ +/* qtip2 v3.0.3 | Plugins: tips modal viewport svg imagemap ie6 | Styles: core basic css3 | qtip2.com | Licensed MIT | Wed May 11 2016 22:31:31 */ + +!function(a,b,c){!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):jQuery&&!jQuery.fn.qtip&&a(jQuery)}(function(d){"use strict";function e(a,b,c,e){this.id=c,this.target=a,this.tooltip=F,this.elements={target:a},this._id=S+"-"+c,this.timers={img:{}},this.options=b,this.plugins={},this.cache={event:{},target:d(),disabled:E,attr:e,onTooltip:E,lastClass:""},this.rendered=this.destroyed=this.disabled=this.waiting=this.hiddenDuringWait=this.positioning=this.triggering=E}function f(a){return a===F||"object"!==d.type(a)}function g(a){return!(d.isFunction(a)||a&&a.attr||a.length||"object"===d.type(a)&&(a.jquery||a.then))}function h(a){var b,c,e,h;return f(a)?E:(f(a.metadata)&&(a.metadata={type:a.metadata}),"content"in a&&(b=a.content,f(b)||b.jquery||b.done?(c=g(b)?E:b,b=a.content={text:c}):c=b.text,"ajax"in b&&(e=b.ajax,h=e&&e.once!==E,delete b.ajax,b.text=function(a,b){var f=c||d(this).attr(b.options.content.attr)||"Loading...",g=d.ajax(d.extend({},e,{context:b})).then(e.success,F,e.error).then(function(a){return a&&h&&b.set("content.text",a),a},function(a,c,d){b.destroyed||0===a.status||b.set("content.text",c+": "+d)});return h?f:(b.set("content.text",f),g)}),"title"in b&&(d.isPlainObject(b.title)&&(b.button=b.title.button,b.title=b.title.text),g(b.title||E)&&(b.title=E))),"position"in a&&f(a.position)&&(a.position={my:a.position,at:a.position}),"show"in a&&f(a.show)&&(a.show=a.show.jquery?{target:a.show}:a.show===D?{ready:D}:{event:a.show}),"hide"in a&&f(a.hide)&&(a.hide=a.hide.jquery?{target:a.hide}:{event:a.hide}),"style"in a&&f(a.style)&&(a.style={classes:a.style}),d.each(R,function(){this.sanitize&&this.sanitize(a)}),a)}function i(a,b){for(var c,d=0,e=a,f=b.split(".");e=e[f[d++]];)d0?setTimeout(d.proxy(a,this),b):void a.call(this)}function m(a){this.tooltip.hasClass(aa)||(clearTimeout(this.timers.show),clearTimeout(this.timers.hide),this.timers.show=l.call(this,function(){this.toggle(D,a)},this.options.show.delay))}function n(a){if(!this.tooltip.hasClass(aa)&&!this.destroyed){var b=d(a.relatedTarget),c=b.closest(W)[0]===this.tooltip[0],e=b[0]===this.options.show.target[0];if(clearTimeout(this.timers.show),clearTimeout(this.timers.hide),this!==b[0]&&"mouse"===this.options.position.target&&c||this.options.hide.fixed&&/mouse(out|leave|move)/.test(a.type)&&(c||e))try{a.preventDefault(),a.stopImmediatePropagation()}catch(f){}else this.timers.hide=l.call(this,function(){this.toggle(E,a)},this.options.hide.delay,this)}}function o(a){!this.tooltip.hasClass(aa)&&this.options.hide.inactive&&(clearTimeout(this.timers.inactive),this.timers.inactive=l.call(this,function(){this.hide(a)},this.options.hide.inactive))}function p(a){this.rendered&&this.tooltip[0].offsetWidth>0&&this.reposition(a)}function q(a,c,e){d(b.body).delegate(a,(c.split?c:c.join("."+S+" "))+"."+S,function(){var a=y.api[d.attr(this,U)];a&&!a.disabled&&e.apply(a,arguments)})}function r(a,c,f){var g,i,j,k,l,m=d(b.body),n=a[0]===b?m:a,o=a.metadata?a.metadata(f.metadata):F,p="html5"===f.metadata.type&&o?o[f.metadata.name]:F,q=a.data(f.metadata.name||"qtipopts");try{q="string"==typeof q?d.parseJSON(q):q}catch(r){}if(k=d.extend(D,{},y.defaults,f,"object"==typeof q?h(q):F,h(p||o)),i=k.position,k.id=c,"boolean"==typeof k.content.text){if(j=a.attr(k.content.attr),k.content.attr===E||!j)return E;k.content.text=j}if(i.container.length||(i.container=m),i.target===E&&(i.target=n),k.show.target===E&&(k.show.target=n),k.show.solo===D&&(k.show.solo=i.container.closest("body")),k.hide.target===E&&(k.hide.target=n),k.position.viewport===D&&(k.position.viewport=i.container),i.container=i.container.eq(0),i.at=new A(i.at,D),i.my=new A(i.my),a.data(S))if(k.overwrite)a.qtip("destroy",!0);else if(k.overwrite===E)return E;return a.attr(T,c),k.suppress&&(l=a.attr("title"))&&a.removeAttr("title").attr(ca,l).attr("title",""),g=new e(a,k,c,!!j),a.data(S,g),g}function s(a){return a.charAt(0).toUpperCase()+a.slice(1)}function t(a,b){var d,e,f=b.charAt(0).toUpperCase()+b.slice(1),g=(b+" "+va.join(f+" ")+f).split(" "),h=0;if(ua[b])return a.css(ua[b]);for(;d=g[h++];)if((e=a.css(d))!==c)return ua[b]=d,e}function u(a,b){return Math.ceil(parseFloat(t(a,b)))}function v(a,b){this._ns="tip",this.options=b,this.offset=b.offset,this.size=[b.width,b.height],this.qtip=a,this.init(a)}function w(a,b){this.options=b,this._ns="-modal",this.qtip=a,this.init(a)}function x(a){this._ns="ie6",this.qtip=a,this.init(a)}var y,z,A,B,C,D=!0,E=!1,F=null,G="x",H="y",I="width",J="height",K="top",L="left",M="bottom",N="right",O="center",P="flipinvert",Q="shift",R={},S="qtip",T="data-hasqtip",U="data-qtip-id",V=["ui-widget","ui-tooltip"],W="."+S,X="click dblclick mousedown mouseup mousemove mouseleave mouseenter".split(" "),Y=S+"-fixed",Z=S+"-default",$=S+"-focus",_=S+"-hover",aa=S+"-disabled",ba="_replacedByqTip",ca="oldtitle",da={ie:function(){var a,c;for(a=4,c=b.createElement("div");(c.innerHTML="")&&c.getElementsByTagName("i")[0];a+=1);return a>4?a:NaN}(),iOS:parseFloat((""+(/CPU.*OS ([0-9_]{1,5})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent)||[0,""])[1]).replace("undefined","3_2").replace("_",".").replace("_",""))||E};z=e.prototype,z._when=function(a){return d.when.apply(d,a)},z.render=function(a){if(this.rendered||this.destroyed)return this;var b=this,c=this.options,e=this.cache,f=this.elements,g=c.content.text,h=c.content.title,i=c.content.button,j=c.position,k=[];return d.attr(this.target[0],"aria-describedby",this._id),e.posClass=this._createPosClass((this.position={my:j.my,at:j.at}).my),this.tooltip=f.tooltip=d("
",{id:this._id,"class":[S,Z,c.style.classes,e.posClass].join(" "),width:c.style.width||"",height:c.style.height||"",tracking:"mouse"===j.target&&j.adjust.mouse,role:"alert","aria-live":"polite","aria-atomic":E,"aria-describedby":this._id+"-content","aria-hidden":D}).toggleClass(aa,this.disabled).attr(U,this.id).data(S,this).appendTo(j.container).append(f.content=d("
",{"class":S+"-content",id:this._id+"-content","aria-atomic":D})),this.rendered=-1,this.positioning=D,h&&(this._createTitle(),d.isFunction(h)||k.push(this._updateTitle(h,E))),i&&this._createButton(),d.isFunction(g)||k.push(this._updateContent(g,E)),this.rendered=D,this._setWidget(),d.each(R,function(a){var c;"render"===this.initialize&&(c=this(b))&&(b.plugins[a]=c)}),this._unassignEvents(),this._assignEvents(),this._when(k).then(function(){b._trigger("render"),b.positioning=E,b.hiddenDuringWait||!c.show.ready&&!a||b.toggle(D,e.event,E),b.hiddenDuringWait=E}),y.api[this.id]=this,this},z.destroy=function(a){function b(){if(!this.destroyed){this.destroyed=D;var a,b=this.target,c=b.attr(ca);this.rendered&&this.tooltip.stop(1,0).find("*").remove().end().remove(),d.each(this.plugins,function(){this.destroy&&this.destroy()});for(a in this.timers)this.timers.hasOwnProperty(a)&&clearTimeout(this.timers[a]);b.removeData(S).removeAttr(U).removeAttr(T).removeAttr("aria-describedby"),this.options.suppress&&c&&b.attr("title",c).removeAttr(ca),this._unassignEvents(),this.options=this.elements=this.cache=this.timers=this.plugins=this.mouse=F,delete y.api[this.id]}}return this.destroyed?this.target:(a===D&&"hide"!==this.triggering||!this.rendered?b.call(this):(this.tooltip.one("tooltiphidden",d.proxy(b,this)),!this.triggering&&this.hide()),this.target)},B=z.checks={builtin:{"^id$":function(a,b,c,e){var f=c===D?y.nextid:c,g=S+"-"+f;f!==E&&f.length>0&&!d("#"+g).length?(this._id=g,this.rendered&&(this.tooltip[0].id=this._id,this.elements.content[0].id=this._id+"-content",this.elements.title[0].id=this._id+"-title")):a[b]=e},"^prerender":function(a,b,c){c&&!this.rendered&&this.render(this.options.show.ready)},"^content.text$":function(a,b,c){this._updateContent(c)},"^content.attr$":function(a,b,c,d){this.options.content.text===this.target.attr(d)&&this._updateContent(this.target.attr(c))},"^content.title$":function(a,b,c){return c?(c&&!this.elements.title&&this._createTitle(),void this._updateTitle(c)):this._removeTitle()},"^content.button$":function(a,b,c){this._updateButton(c)},"^content.title.(text|button)$":function(a,b,c){this.set("content."+b,c)},"^position.(my|at)$":function(a,b,c){"string"==typeof c&&(this.position[b]=a[b]=new A(c,"at"===b))},"^position.container$":function(a,b,c){this.rendered&&this.tooltip.appendTo(c)},"^show.ready$":function(a,b,c){c&&(!this.rendered&&this.render(D)||this.toggle(D))},"^style.classes$":function(a,b,c,d){this.rendered&&this.tooltip.removeClass(d).addClass(c)},"^style.(width|height)":function(a,b,c){this.rendered&&this.tooltip.css(b,c)},"^style.widget|content.title":function(){this.rendered&&this._setWidget()},"^style.def":function(a,b,c){this.rendered&&this.tooltip.toggleClass(Z,!!c)},"^events.(render|show|move|hide|focus|blur)$":function(a,b,c){this.rendered&&this.tooltip[(d.isFunction(c)?"":"un")+"bind"]("tooltip"+b,c)},"^(show|hide|position).(event|target|fixed|inactive|leave|distance|viewport|adjust)":function(){if(this.rendered){var a=this.options.position;this.tooltip.attr("tracking","mouse"===a.target&&a.adjust.mouse),this._unassignEvents(),this._assignEvents()}}}},z.get=function(a){if(this.destroyed)return this;var b=i(this.options,a.toLowerCase()),c=b[0][b[1]];return c.precedance?c.string():c};var ea=/^position\.(my|at|adjust|target|container|viewport)|style|content|show\.ready/i,fa=/^prerender|show\.ready/i;z.set=function(a,b){if(this.destroyed)return this;var c,e=this.rendered,f=E,g=this.options;return"string"==typeof a?(c=a,a={},a[c]=b):a=d.extend({},a),d.each(a,function(b,c){if(e&&fa.test(b))return void delete a[b];var h,j=i(g,b.toLowerCase());h=j[0][j[1]],j[0][j[1]]=c&&c.nodeType?d(c):c,f=ea.test(b)||f,a[b]=[j[0],j[1],c,h]}),h(g),this.positioning=D,d.each(a,d.proxy(j,this)),this.positioning=E,this.rendered&&this.tooltip[0].offsetWidth>0&&f&&this.reposition("mouse"===g.position.target?F:this.cache.event),this},z._update=function(a,b){var c=this,e=this.cache;return this.rendered&&a?(d.isFunction(a)&&(a=a.call(this.elements.target,e.event,this)||""),d.isFunction(a.then)?(e.waiting=D,a.then(function(a){return e.waiting=E,c._update(a,b)},F,function(a){return c._update(a,b)})):a===E||!a&&""!==a?E:(a.jquery&&a.length>0?b.empty().append(a.css({display:"block",visibility:"visible"})):b.html(a),this._waitForContent(b).then(function(a){c.rendered&&c.tooltip[0].offsetWidth>0&&c.reposition(e.event,!a.length)}))):E},z._waitForContent=function(a){var b=this.cache;return b.waiting=D,(d.fn.imagesLoaded?a.imagesLoaded():(new d.Deferred).resolve([])).done(function(){b.waiting=E}).promise()},z._updateContent=function(a,b){this._update(a,this.elements.content,b)},z._updateTitle=function(a,b){this._update(a,this.elements.title,b)===E&&this._removeTitle(E)},z._createTitle=function(){var a=this.elements,b=this._id+"-title";a.titlebar&&this._removeTitle(),a.titlebar=d("
",{"class":S+"-titlebar "+(this.options.style.widget?k("header"):"")}).append(a.title=d("
",{id:b,"class":S+"-title","aria-atomic":D})).insertBefore(a.content).delegate(".qtip-close","mousedown keydown mouseup keyup mouseout",function(a){d(this).toggleClass("ui-state-active ui-state-focus","down"===a.type.substr(-4))}).delegate(".qtip-close","mouseover mouseout",function(a){d(this).toggleClass("ui-state-hover","mouseover"===a.type)}),this.options.content.button&&this._createButton()},z._removeTitle=function(a){var b=this.elements;b.title&&(b.titlebar.remove(),b.titlebar=b.title=b.button=F,a!==E&&this.reposition())},z._createPosClass=function(a){return S+"-pos-"+(a||this.options.position.my).abbrev()},z.reposition=function(c,e){if(!this.rendered||this.positioning||this.destroyed)return this;this.positioning=D;var f,g,h,i,j=this.cache,k=this.tooltip,l=this.options.position,m=l.target,n=l.my,o=l.at,p=l.viewport,q=l.container,r=l.adjust,s=r.method.split(" "),t=k.outerWidth(E),u=k.outerHeight(E),v=0,w=0,x=k.css("position"),y={left:0,top:0},z=k[0].offsetWidth>0,A=c&&"scroll"===c.type,B=d(a),C=q[0].ownerDocument,F=this.mouse;if(d.isArray(m)&&2===m.length)o={x:L,y:K},y={left:m[0],top:m[1]};else if("mouse"===m)o={x:L,y:K},(!r.mouse||this.options.hide.distance)&&j.origin&&j.origin.pageX?c=j.origin:!c||c&&("resize"===c.type||"scroll"===c.type)?c=j.event:F&&F.pageX&&(c=F),"static"!==x&&(y=q.offset()),C.body.offsetWidth!==(a.innerWidth||C.documentElement.clientWidth)&&(g=d(b.body).offset()),y={left:c.pageX-y.left+(g&&g.left||0),top:c.pageY-y.top+(g&&g.top||0)},r.mouse&&A&&F&&(y.left-=(F.scrollX||0)-B.scrollLeft(),y.top-=(F.scrollY||0)-B.scrollTop());else{if("event"===m?c&&c.target&&"scroll"!==c.type&&"resize"!==c.type?j.target=d(c.target):c.target||(j.target=this.elements.target):"event"!==m&&(j.target=d(m.jquery?m:this.elements.target)),m=j.target,m=d(m).eq(0),0===m.length)return this;m[0]===b||m[0]===a?(v=da.iOS?a.innerWidth:m.width(),w=da.iOS?a.innerHeight:m.height(),m[0]===a&&(y={top:(p||m).scrollTop(),left:(p||m).scrollLeft()})):R.imagemap&&m.is("area")?f=R.imagemap(this,m,o,R.viewport?s:E):R.svg&&m&&m[0].ownerSVGElement?f=R.svg(this,m,o,R.viewport?s:E):(v=m.outerWidth(E),w=m.outerHeight(E),y=m.offset()),f&&(v=f.width,w=f.height,g=f.offset,y=f.position),y=this.reposition.offset(m,y,q),(da.iOS>3.1&&da.iOS<4.1||da.iOS>=4.3&&da.iOS<4.33||!da.iOS&&"fixed"===x)&&(y.left-=B.scrollLeft(),y.top-=B.scrollTop()),(!f||f&&f.adjustable!==E)&&(y.left+=o.x===N?v:o.x===O?v/2:0,y.top+=o.y===M?w:o.y===O?w/2:0)}return y.left+=r.x+(n.x===N?-t:n.x===O?-t/2:0),y.top+=r.y+(n.y===M?-u:n.y===O?-u/2:0),R.viewport?(h=y.adjusted=R.viewport(this,y,l,v,w,t,u),g&&h.left&&(y.left+=g.left),g&&h.top&&(y.top+=g.top),h.my&&(this.position.my=h.my)):y.adjusted={left:0,top:0},j.posClass!==(i=this._createPosClass(this.position.my))&&(j.posClass=i,k.removeClass(j.posClass).addClass(i)),this._trigger("move",[y,p.elem||p],c)?(delete y.adjusted,e===E||!z||isNaN(y.left)||isNaN(y.top)||"mouse"===m||!d.isFunction(l.effect)?k.css(y):d.isFunction(l.effect)&&(l.effect.call(k,this,d.extend({},y)),k.queue(function(a){d(this).css({opacity:"",height:""}),da.ie&&this.style.removeAttribute("filter"),a()})),this.positioning=E,this):this},z.reposition.offset=function(a,c,e){function f(a,b){c.left+=b*a.scrollLeft(),c.top+=b*a.scrollTop()}if(!e[0])return c;var g,h,i,j,k=d(a[0].ownerDocument),l=!!da.ie&&"CSS1Compat"!==b.compatMode,m=e[0];do"static"!==(h=d.css(m,"position"))&&("fixed"===h?(i=m.getBoundingClientRect(),f(k,-1)):(i=d(m).position(),i.left+=parseFloat(d.css(m,"borderLeftWidth"))||0,i.top+=parseFloat(d.css(m,"borderTopWidth"))||0),c.left-=i.left+(parseFloat(d.css(m,"marginLeft"))||0),c.top-=i.top+(parseFloat(d.css(m,"marginTop"))||0),g||"hidden"===(j=d.css(m,"overflow"))||"visible"===j||(g=d(m)));while(m=m.offsetParent);return g&&(g[0]!==k[0]||l)&&f(g,1),c};var ga=(A=z.reposition.Corner=function(a,b){a=(""+a).replace(/([A-Z])/," $1").replace(/middle/gi,O).toLowerCase(),this.x=(a.match(/left|right/i)||a.match(/center/)||["inherit"])[0].toLowerCase(),this.y=(a.match(/top|bottom|center/i)||["inherit"])[0].toLowerCase(),this.forceY=!!b;var c=a.charAt(0);this.precedance="t"===c||"b"===c?H:G}).prototype;ga.invert=function(a,b){this[a]=this[a]===L?N:this[a]===N?L:b||this[a]},ga.string=function(a){var b=this.x,c=this.y,d=b!==c?"center"===b||"center"!==c&&(this.precedance===H||this.forceY)?[c,b]:[b,c]:[b];return a!==!1?d.join(" "):d},ga.abbrev=function(){var a=this.string(!1);return a[0].charAt(0)+(a[1]&&a[1].charAt(0)||"")},ga.clone=function(){return new A(this.string(),this.forceY)},z.toggle=function(a,c){var e=this.cache,f=this.options,g=this.tooltip;if(c){if(/over|enter/.test(c.type)&&e.event&&/out|leave/.test(e.event.type)&&f.show.target.add(c.target).length===f.show.target.length&&g.has(c.relatedTarget).length)return this;e.event=d.event.fix(c)}if(this.waiting&&!a&&(this.hiddenDuringWait=D),!this.rendered)return a?this.render(1):this;if(this.destroyed||this.disabled)return this;var h,i,j,k=a?"show":"hide",l=this.options[k],m=this.options.position,n=this.options.content,o=this.tooltip.css("width"),p=this.tooltip.is(":visible"),q=a||1===l.target.length,r=!c||l.target.length<2||e.target[0]===c.target;return(typeof a).search("boolean|number")&&(a=!p),h=!g.is(":animated")&&p===a&&r,i=h?F:!!this._trigger(k,[90]),this.destroyed?this:(i!==E&&a&&this.focus(c),!i||h?this:(d.attr(g[0],"aria-hidden",!a),a?(this.mouse&&(e.origin=d.event.fix(this.mouse)),d.isFunction(n.text)&&this._updateContent(n.text,E),d.isFunction(n.title)&&this._updateTitle(n.title,E),!C&&"mouse"===m.target&&m.adjust.mouse&&(d(b).bind("mousemove."+S,this._storeMouse),C=D),o||g.css("width",g.outerWidth(E)),this.reposition(c,arguments[2]),o||g.css("width",""),l.solo&&("string"==typeof l.solo?d(l.solo):d(W,l.solo)).not(g).not(l.target).qtip("hide",new d.Event("tooltipsolo"))):(clearTimeout(this.timers.show),delete e.origin,C&&!d(W+'[tracking="true"]:visible',l.solo).not(g).length&&(d(b).unbind("mousemove."+S),C=E),this.blur(c)),j=d.proxy(function(){a?(da.ie&&g[0].style.removeAttribute("filter"),g.css("overflow",""),"string"==typeof l.autofocus&&d(this.options.show.autofocus,g).focus(),this.options.show.target.trigger("qtip-"+this.id+"-inactive")):g.css({display:"",visibility:"",opacity:"",left:"",top:""}),this._trigger(a?"visible":"hidden")},this),l.effect===E||q===E?(g[k](),j()):d.isFunction(l.effect)?(g.stop(1,1),l.effect.call(g,this),g.queue("fx",function(a){j(),a()})):g.fadeTo(90,a?1:0,j),a&&l.target.trigger("qtip-"+this.id+"-inactive"),this))},z.show=function(a){return this.toggle(D,a)},z.hide=function(a){return this.toggle(E,a)},z.focus=function(a){if(!this.rendered||this.destroyed)return this;var b=d(W),c=this.tooltip,e=parseInt(c[0].style.zIndex,10),f=y.zindex+b.length;return c.hasClass($)||this._trigger("focus",[f],a)&&(e!==f&&(b.each(function(){this.style.zIndex>e&&(this.style.zIndex=this.style.zIndex-1)}),b.filter("."+$).qtip("blur",a)),c.addClass($)[0].style.zIndex=f),this},z.blur=function(a){return!this.rendered||this.destroyed?this:(this.tooltip.removeClass($),this._trigger("blur",[this.tooltip.css("zIndex")],a),this)},z.disable=function(a){return this.destroyed?this:("toggle"===a?a=!(this.rendered?this.tooltip.hasClass(aa):this.disabled):"boolean"!=typeof a&&(a=D),this.rendered&&this.tooltip.toggleClass(aa,a).attr("aria-disabled",a),this.disabled=!!a,this)},z.enable=function(){return this.disable(E)},z._createButton=function(){var a=this,b=this.elements,c=b.tooltip,e=this.options.content.button,f="string"==typeof e,g=f?e:"Close tooltip";b.button&&b.button.remove(),e.jquery?b.button=e:b.button=d("",{"class":"qtip-close "+(this.options.style.widget?"":S+"-icon"),title:g,"aria-label":g}).prepend(d("",{"class":"ui-icon ui-icon-close",html:"×"})),b.button.appendTo(b.titlebar||c).attr("role","button").click(function(b){return c.hasClass(aa)||a.hide(b),E})},z._updateButton=function(a){if(!this.rendered)return E;var b=this.elements.button;a?this._createButton():b.remove()},z._setWidget=function(){var a=this.options.style.widget,b=this.elements,c=b.tooltip,d=c.hasClass(aa);c.removeClass(aa),aa=a?"ui-state-disabled":"qtip-disabled",c.toggleClass(aa,d),c.toggleClass("ui-helper-reset "+k(),a).toggleClass(Z,this.options.style.def&&!a),b.content&&b.content.toggleClass(k("content"),a),b.titlebar&&b.titlebar.toggleClass(k("header"),a),b.button&&b.button.toggleClass(S+"-icon",!a)},z._storeMouse=function(a){return(this.mouse=d.event.fix(a)).type="mousemove",this},z._bind=function(a,b,c,e,f){if(a&&c&&b.length){var g="."+this._id+(e?"-"+e:"");return d(a).bind((b.split?b:b.join(g+" "))+g,d.proxy(c,f||this)),this}},z._unbind=function(a,b){return a&&d(a).unbind("."+this._id+(b?"-"+b:"")),this},z._trigger=function(a,b,c){var e=new d.Event("tooltip"+a);return e.originalEvent=c&&d.extend({},c)||this.cache.event||F,this.triggering=a,this.tooltip.trigger(e,[this].concat(b||[])),this.triggering=E,!e.isDefaultPrevented()},z._bindEvents=function(a,b,c,e,f,g){var h=c.filter(e).add(e.filter(c)),i=[];h.length&&(d.each(b,function(b,c){var e=d.inArray(c,a);e>-1&&i.push(a.splice(e,1)[0])}),i.length&&(this._bind(h,i,function(a){var b=this.rendered?this.tooltip[0].offsetWidth>0:!1;(b?g:f).call(this,a)}),c=c.not(h),e=e.not(h))),this._bind(c,a,f),this._bind(e,b,g)},z._assignInitialEvents=function(a){function b(a){return this.disabled||this.destroyed?E:(this.cache.event=a&&d.event.fix(a),this.cache.target=a&&d(a.target),clearTimeout(this.timers.show),void(this.timers.show=l.call(this,function(){this.render("object"==typeof a||c.show.ready)},c.prerender?0:c.show.delay)))}var c=this.options,e=c.show.target,f=c.hide.target,g=c.show.event?d.trim(""+c.show.event).split(" "):[],h=c.hide.event?d.trim(""+c.hide.event).split(" "):[];this._bind(this.elements.target,["remove","removeqtip"],function(){this.destroy(!0)},"destroy"),/mouse(over|enter)/i.test(c.show.event)&&!/mouse(out|leave)/i.test(c.hide.event)&&h.push("mouseleave"),this._bind(e,"mousemove",function(a){this._storeMouse(a),this.cache.onTarget=D}),this._bindEvents(g,h,e,f,b,function(){return this.timers?void clearTimeout(this.timers.show):E}),(c.show.ready||c.prerender)&&b.call(this,a)},z._assignEvents=function(){var c=this,e=this.options,f=e.position,g=this.tooltip,h=e.show.target,i=e.hide.target,j=f.container,k=f.viewport,l=d(b),q=d(a),r=e.show.event?d.trim(""+e.show.event).split(" "):[],s=e.hide.event?d.trim(""+e.hide.event).split(" "):[];d.each(e.events,function(a,b){c._bind(g,"toggle"===a?["tooltipshow","tooltiphide"]:["tooltip"+a],b,null,g)}),/mouse(out|leave)/i.test(e.hide.event)&&"window"===e.hide.leave&&this._bind(l,["mouseout","blur"],function(a){/select|option/.test(a.target.nodeName)||a.relatedTarget||this.hide(a)}),e.hide.fixed?i=i.add(g.addClass(Y)):/mouse(over|enter)/i.test(e.show.event)&&this._bind(i,"mouseleave",function(){clearTimeout(this.timers.show)}),(""+e.hide.event).indexOf("unfocus")>-1&&this._bind(j.closest("html"),["mousedown","touchstart"],function(a){var b=d(a.target),c=this.rendered&&!this.tooltip.hasClass(aa)&&this.tooltip[0].offsetWidth>0,e=b.parents(W).filter(this.tooltip[0]).length>0;b[0]===this.target[0]||b[0]===this.tooltip[0]||e||this.target.has(b[0]).length||!c||this.hide(a)}),"number"==typeof e.hide.inactive&&(this._bind(h,"qtip-"+this.id+"-inactive",o,"inactive"),this._bind(i.add(g),y.inactiveEvents,o)),this._bindEvents(r,s,h,i,m,n),this._bind(h.add(g),"mousemove",function(a){if("number"==typeof e.hide.distance){var b=this.cache.origin||{},c=this.options.hide.distance,d=Math.abs;(d(a.pageX-b.pageX)>=c||d(a.pageY-b.pageY)>=c)&&this.hide(a)}this._storeMouse(a)}),"mouse"===f.target&&f.adjust.mouse&&(e.hide.event&&this._bind(h,["mouseenter","mouseleave"],function(a){return this.cache?void(this.cache.onTarget="mouseenter"===a.type):E}),this._bind(l,"mousemove",function(a){this.rendered&&this.cache.onTarget&&!this.tooltip.hasClass(aa)&&this.tooltip[0].offsetWidth>0&&this.reposition(a)})),(f.adjust.resize||k.length)&&this._bind(d.event.special.resize?k:q,"resize",p),f.adjust.scroll&&this._bind(q.add(f.container),"scroll",p)},z._unassignEvents=function(){var c=this.options,e=c.show.target,f=c.hide.target,g=d.grep([this.elements.target[0],this.rendered&&this.tooltip[0],c.position.container[0],c.position.viewport[0],c.position.container.closest("html")[0],a,b],function(a){return"object"==typeof a});e&&e.toArray&&(g=g.concat(e.toArray())),f&&f.toArray&&(g=g.concat(f.toArray())),this._unbind(g)._unbind(g,"destroy")._unbind(g,"inactive")},d(function(){q(W,["mouseenter","mouseleave"],function(a){var b="mouseenter"===a.type,c=d(a.currentTarget),e=d(a.relatedTarget||a.target),f=this.options;b?(this.focus(a),c.hasClass(Y)&&!c.hasClass(aa)&&clearTimeout(this.timers.hide)):"mouse"===f.position.target&&f.position.adjust.mouse&&f.hide.event&&f.show.target&&!e.closest(f.show.target[0]).length&&this.hide(a),c.toggleClass(_,b)}),q("["+U+"]",X,o)}),y=d.fn.qtip=function(a,b,e){var f=(""+a).toLowerCase(),g=F,i=d.makeArray(arguments).slice(1),j=i[i.length-1],k=this[0]?d.data(this[0],S):F;return!arguments.length&&k||"api"===f?k:"string"==typeof a?(this.each(function(){var a=d.data(this,S);if(!a)return D;if(j&&j.timeStamp&&(a.cache.event=j),!b||"option"!==f&&"options"!==f)a[f]&&a[f].apply(a,i);else{if(e===c&&!d.isPlainObject(b))return g=a.get(b),E;a.set(b,e)}}),g!==F?g:this):"object"!=typeof a&&arguments.length?void 0:(k=h(d.extend(D,{},a)),this.each(function(a){var b,c;return c=d.isArray(k.id)?k.id[a]:k.id,c=!c||c===E||c.length<1||y.api[c]?y.nextid++:c,b=r(d(this),c,k),b===E?D:(y.api[c]=b,d.each(R,function(){"initialize"===this.initialize&&this(b)}),void b._assignInitialEvents(j))}))},d.qtip=e,y.api={},d.each({attr:function(a,b){if(this.length){var c=this[0],e="title",f=d.data(c,"qtip");if(a===e&&f&&f.options&&"object"==typeof f&&"object"==typeof f.options&&f.options.suppress)return arguments.length<2?d.attr(c,ca):(f&&f.options.content.attr===e&&f.cache.attr&&f.set("content.text",b),this.attr(ca,b))}return d.fn["attr"+ba].apply(this,arguments)},clone:function(a){var b=d.fn["clone"+ba].apply(this,arguments);return a||b.filter("["+ca+"]").attr("title",function(){return d.attr(this,ca)}).removeAttr(ca),b}},function(a,b){if(!b||d.fn[a+ba])return D;var c=d.fn[a+ba]=d.fn[a];d.fn[a]=function(){return b.apply(this,arguments)||c.apply(this,arguments)}}),d.ui||(d["cleanData"+ba]=d.cleanData,d.cleanData=function(a){for(var b,c=0;(b=d(a[c])).length;c++)if(b.attr(T))try{b.triggerHandler("removeqtip")}catch(e){}d["cleanData"+ba].apply(this,arguments)}),y.version="3.0.3",y.nextid=0,y.inactiveEvents=X,y.zindex=15e3,y.defaults={prerender:E,id:E,overwrite:D,suppress:D,content:{text:D,attr:"title",title:E,button:E},position:{my:"top left",at:"bottom right",target:E,container:E,viewport:E,adjust:{x:0,y:0,mouse:D,scroll:D,resize:D,method:"flipinvert flipinvert"},effect:function(a,b){d(this).animate(b,{duration:200,queue:E})}},show:{target:E,event:"mouseenter",effect:D,delay:90,solo:E,ready:E,autofocus:E},hide:{target:E,event:"mouseleave",effect:D,delay:0,fixed:E,inactive:E,leave:"window",distance:E},style:{classes:"",widget:E,width:E,height:E,def:D},events:{render:F,move:F,show:F,hide:F,toggle:F,visible:F,hidden:F,focus:F,blur:F}};var ha,ia,ja,ka,la,ma="margin",na="border",oa="color",pa="background-color",qa="transparent",ra=" !important",sa=!!b.createElement("canvas").getContext,ta=/rgba?\(0, 0, 0(, 0)?\)|transparent|#123456/i,ua={},va=["Webkit","O","Moz","ms"];sa?(ka=a.devicePixelRatio||1,la=function(){var a=b.createElement("canvas").getContext("2d");return a.backingStorePixelRatio||a.webkitBackingStorePixelRatio||a.mozBackingStorePixelRatio||a.msBackingStorePixelRatio||a.oBackingStorePixelRatio||1}(),ja=ka/la):ia=function(a,b,c){return"'},d.extend(v.prototype,{init:function(a){var b,c;c=this.element=a.elements.tip=d("
",{"class":S+"-tip"}).prependTo(a.tooltip),sa?(b=d("").appendTo(this.element)[0].getContext("2d"),b.lineJoin="miter",b.miterLimit=1e5,b.save()):(b=ia("shape",'coordorigin="0,0"',"position:absolute;"),this.element.html(b+b),a._bind(d("*",c).add(c),["click","mousedown"],function(a){a.stopPropagation()},this._ns)),a._bind(a.tooltip,"tooltipmove",this.reposition,this._ns,this),this.create()},_swapDimensions:function(){this.size[0]=this.options.height,this.size[1]=this.options.width},_resetDimensions:function(){this.size[0]=this.options.width,this.size[1]=this.options.height},_useTitle:function(a){var b=this.qtip.elements.titlebar;return b&&(a.y===K||a.y===O&&this.element.position().top+this.size[1]/2+this.options.offsetl&&!ta.test(e[1])&&(e[0]=e[1]),this.border=l=p.border!==D?p.border:l):this.border=l=0,k=this.size=this._calculateSize(b),n.css({width:k[0],height:k[1],lineHeight:k[1]+"px"}),j=b.precedance===H?[s(r.x===L?l:r.x===N?k[0]-q[0]-l:(k[0]-q[0])/2),s(r.y===K?k[1]-q[1]:0)]:[s(r.x===L?k[0]-q[0]:0),s(r.y===K?l:r.y===M?k[1]-q[1]-l:(k[1]-q[1])/2)],sa?(g=o[0].getContext("2d"),g.restore(),g.save(),g.clearRect(0,0,6e3,6e3),h=this._calculateTip(r,q,ja),i=this._calculateTip(r,this.size,ja),o.attr(I,k[0]*ja).attr(J,k[1]*ja),o.css(I,k[0]).css(J,k[1]),this._drawCoords(g,i),g.fillStyle=e[1],g.fill(),g.translate(j[0]*ja,j[1]*ja),this._drawCoords(g,h),g.fillStyle=e[0],g.fill()):(h=this._calculateTip(r),h="m"+h[0]+","+h[1]+" l"+h[2]+","+h[3]+" "+h[4]+","+h[5]+" xe",j[2]=l&&/^(r|b)/i.test(b.string())?8===da.ie?2:1:0,o.css({coordsize:k[0]+l+" "+k[1]+l,antialias:""+(r.string().indexOf(O)>-1),left:j[0]-j[2]*Number(f===G),top:j[1]-j[2]*Number(f===H),width:k[0]+l,height:k[1]+l}).each(function(a){var b=d(this);b[b.prop?"prop":"attr"]({coordsize:k[0]+l+" "+k[1]+l,path:h,fillcolor:e[0],filled:!!a,stroked:!a}).toggle(!(!l&&!a)),!a&&b.html(ia("stroke",'weight="'+2*l+'px" color="'+e[1]+'" miterlimit="1000" joinstyle="miter"'))})),a.opera&&setTimeout(function(){m.tip.css({display:"inline-block",visibility:"visible"})},1),c!==E&&this.calculate(b,k)},calculate:function(a,b){if(!this.enabled)return E;var c,e,f=this,g=this.qtip.elements,h=this.element,i=this.options.offset,j={}; +return a=a||this.corner,c=a.precedance,b=b||this._calculateSize(a),e=[a.x,a.y],c===G&&e.reverse(),d.each(e,function(d,e){var h,k,l;e===O?(h=c===H?L:K,j[h]="50%",j[ma+"-"+h]=-Math.round(b[c===H?0:1]/2)+i):(h=f._parseWidth(a,e,g.tooltip),k=f._parseWidth(a,e,g.content),l=f._parseRadius(a),j[e]=Math.max(-f.border,d?k:i+(l>h?l:-h)))}),j[a[c]]-=b[c===G?0:1],h.css({margin:"",top:"",bottom:"",left:"",right:""}).css(j),j},reposition:function(a,b,d){function e(a,b,c,d,e){a===Q&&j.precedance===b&&k[d]&&j[c]!==O?j.precedance=j.precedance===G?H:G:a!==Q&&k[d]&&(j[b]=j[b]===O?k[d]>0?d:e:j[b]===d?e:d)}function f(a,b,e){j[a]===O?p[ma+"-"+b]=o[a]=g[ma+"-"+b]-k[b]:(h=g[e]!==c?[k[b],-g[b]]:[-k[b],g[b]],(o[a]=Math.max(h[0],h[1]))>h[0]&&(d[b]-=k[b],o[b]=E),p[g[e]!==c?e:b]=o[a])}if(this.enabled){var g,h,i=b.cache,j=this.corner.clone(),k=d.adjusted,l=b.options.position.adjust.method.split(" "),m=l[0],n=l[1]||l[0],o={left:E,top:E,x:0,y:0},p={};this.corner.fixed!==D&&(e(m,G,H,L,N),e(n,H,G,K,M),j.string()===i.corner.string()&&i.cornerTop===k.top&&i.cornerLeft===k.left||this.update(j,E)),g=this.calculate(j),g.right!==c&&(g.left=-g.right),g.bottom!==c&&(g.top=-g.bottom),g.user=this.offset,o.left=m===Q&&!!k.left,o.left&&f(G,L,N),o.top=n===Q&&!!k.top,o.top&&f(H,K,M),this.element.css(p).toggle(!(o.x&&o.y||j.x===O&&o.y||j.y===O&&o.x)),d.left-=g.left.charAt?g.user:m!==Q||o.top||!o.left&&!o.top?g.left+this.border:0,d.top-=g.top.charAt?g.user:n!==Q||o.left||!o.left&&!o.top?g.top+this.border:0,i.cornerLeft=k.left,i.cornerTop=k.top,i.corner=j.clone()}},destroy:function(){this.qtip._unbind(this.qtip.tooltip,this._ns),this.qtip.elements.tip&&this.qtip.elements.tip.find("*").remove().end().remove()}}),ha=R.tip=function(a){return new v(a,a.options.style.tip)},ha.initialize="render",ha.sanitize=function(a){if(a.style&&"tip"in a.style){var b=a.style.tip;"object"!=typeof b&&(b=a.style.tip={corner:b}),/string|boolean/i.test(typeof b.corner)||(b.corner=D)}},B.tip={"^position.my|style.tip.(corner|mimic|border)$":function(){this.create(),this.qtip.reposition()},"^style.tip.(height|width)$":function(a){this.size=[a.width,a.height],this.update(),this.qtip.reposition()},"^content.title|style.(classes|widget)$":function(){this.update()}},d.extend(D,y.defaults,{style:{tip:{corner:D,mimic:E,width:6,height:6,border:D,offset:0}}});var wa,xa,ya="qtip-modal",za="."+ya;xa=function(){function a(a){if(d.expr[":"].focusable)return d.expr[":"].focusable;var b,c,e,f=!isNaN(d.attr(a,"tabindex")),g=a.nodeName&&a.nodeName.toLowerCase();return"area"===g?(b=a.parentNode,c=b.name,a.href&&c&&"map"===b.nodeName.toLowerCase()?(e=d("img[usemap=#"+c+"]")[0],!!e&&e.is(":visible")):!1):/input|select|textarea|button|object/.test(g)?!a.disabled:"a"===g?a.href||f:f}function c(a){j.length<1&&a.length?a.not("body").blur():j.first().focus()}function e(a){if(h.is(":visible")){var b,e=d(a.target),g=f.tooltip,i=e.closest(W);b=i.length<1?E:parseInt(i[0].style.zIndex,10)>parseInt(g[0].style.zIndex,10),b||e.closest(W)[0]===g[0]||c(e)}}var f,g,h,i=this,j={};d.extend(i,{init:function(){return h=i.elem=d("
",{id:"qtip-overlay",html:"
",mousedown:function(){return E}}).hide(),d(b.body).bind("focusin"+za,e),d(b).bind("keydown"+za,function(a){f&&f.options.show.modal.escape&&27===a.keyCode&&f.hide(a)}),h.bind("click"+za,function(a){f&&f.options.show.modal.blur&&f.hide(a)}),i},update:function(b){f=b,j=b.options.show.modal.stealfocus!==E?b.tooltip.find("*").filter(function(){return a(this)}):[]},toggle:function(a,e,j){var k=a.tooltip,l=a.options.show.modal,m=l.effect,n=e?"show":"hide",o=h.is(":visible"),p=d(za).filter(":visible:not(:animated)").not(k);return i.update(a),e&&l.stealfocus!==E&&c(d(":focus")),h.toggleClass("blurs",l.blur),e&&h.appendTo(b.body),h.is(":animated")&&o===e&&g!==E||!e&&p.length?i:(h.stop(D,E),d.isFunction(m)?m.call(h,e):m===E?h[n]():h.fadeTo(parseInt(j,10)||90,e?1:0,function(){e||h.hide()}),e||h.queue(function(a){h.css({left:"",top:""}),d(za).length||h.detach(),a()}),g=e,f.destroyed&&(f=F),i)}}),i.init()},xa=new xa,d.extend(w.prototype,{init:function(a){var b=a.tooltip;return this.options.on?(a.elements.overlay=xa.elem,b.addClass(ya).css("z-index",y.modal_zindex+d(za).length),a._bind(b,["tooltipshow","tooltiphide"],function(a,c,e){var f=a.originalEvent;if(a.target===b[0])if(f&&"tooltiphide"===a.type&&/mouse(leave|enter)/.test(f.type)&&d(f.relatedTarget).closest(xa.elem[0]).length)try{a.preventDefault()}catch(g){}else(!f||f&&"tooltipsolo"!==f.type)&&this.toggle(a,"tooltipshow"===a.type,e)},this._ns,this),a._bind(b,"tooltipfocus",function(a,c){if(!a.isDefaultPrevented()&&a.target===b[0]){var e=d(za),f=y.modal_zindex+e.length,g=parseInt(b[0].style.zIndex,10);xa.elem[0].style.zIndex=f-1,e.each(function(){this.style.zIndex>g&&(this.style.zIndex-=1)}),e.filter("."+$).qtip("blur",a.originalEvent),b.addClass($)[0].style.zIndex=f,xa.update(c);try{a.preventDefault()}catch(h){}}},this._ns,this),void a._bind(b,"tooltiphide",function(a){a.target===b[0]&&d(za).filter(":visible").not(b).last().qtip("focus",a)},this._ns,this)):this},toggle:function(a,b,c){return a&&a.isDefaultPrevented()?this:void xa.toggle(this.qtip,!!b,c)},destroy:function(){this.qtip.tooltip.removeClass(ya),this.qtip._unbind(this.qtip.tooltip,this._ns),xa.toggle(this.qtip,E),delete this.qtip.elements.overlay}}),wa=R.modal=function(a){return new w(a,a.options.show.modal)},wa.sanitize=function(a){a.show&&("object"!=typeof a.show.modal?a.show.modal={on:!!a.show.modal}:"undefined"==typeof a.show.modal.on&&(a.show.modal.on=D))},y.modal_zindex=y.zindex-200,wa.initialize="render",B.modal={"^show.modal.(on|blur)$":function(){this.destroy(),this.init(),this.qtip.elems.overlay.toggle(this.qtip.tooltip[0].offsetWidth>0)}},d.extend(D,y.defaults,{show:{modal:{on:E,effect:D,blur:D,stealfocus:D,escape:D}}}),R.viewport=function(c,d,e,f,g,h,i){function j(a,b,c,e,f,g,h,i,j){var k=d[f],s=u[a],t=v[a],w=c===Q,x=s===f?j:s===g?-j:-j/2,y=t===f?i:t===g?-i:-i/2,z=q[f]+r[f]-(n?0:m[f]),A=z-k,B=k+j-(h===I?o:p)-z,C=x-(u.precedance===a||s===u[b]?y:0)-(t===O?i/2:0);return w?(C=(s===f?1:-1)*x,d[f]+=A>0?A:B>0?-B:0,d[f]=Math.max(-m[f]+r[f],k-C,Math.min(Math.max(-m[f]+r[f]+(h===I?o:p),k+C),d[f],"center"===s?k-x:1e9))):(e*=c===P?2:0,A>0&&(s!==f||B>0)?(d[f]-=C+e,l.invert(a,f)):B>0&&(s!==g||A>0)&&(d[f]-=(s===O?-C:C)+e,l.invert(a,g)),d[f]B&&(d[f]=k,l=u.clone())),d[f]-k}var k,l,m,n,o,p,q,r,s=e.target,t=c.elements.tooltip,u=e.my,v=e.at,w=e.adjust,x=w.method.split(" "),y=x[0],z=x[1]||x[0],A=e.viewport,B=e.container,C={left:0,top:0};return A.jquery&&s[0]!==a&&s[0]!==b.body&&"none"!==w.method?(m=B.offset()||C,n="static"===B.css("position"),k="fixed"===t.css("position"),o=A[0]===a?A.width():A.outerWidth(E),p=A[0]===a?A.height():A.outerHeight(E),q={left:k?0:A.scrollLeft(),top:k?0:A.scrollTop()},r=A.offset()||C,"shift"===y&&"shift"===z||(l=u.clone()),C={left:"none"!==y?j(G,H,y,w.x,L,N,I,f,h):0,top:"none"!==z?j(H,G,z,w.y,K,M,J,g,i):0,my:l}):C},R.polys={polygon:function(a,b){var c,d,e,f={width:0,height:0,position:{top:1e10,right:0,bottom:0,left:1e10},adjustable:E},g=0,h=[],i=1,j=1,k=0,l=0;for(g=a.length;g--;)c=[parseInt(a[--g],10),parseInt(a[g+1],10)],c[0]>f.position.right&&(f.position.right=c[0]),c[0]f.position.bottom&&(f.position.bottom=c[1]),c[1]0&&e>0&&i>0&&j>0;)for(d=Math.floor(d/2),e=Math.floor(e/2),b.x===L?i=d:b.x===N?i=f.width-d:i+=Math.floor(d/2),b.y===K?j=e:b.y===M?j=f.height-e:j+=Math.floor(e/2),g=h.length;g--&&!(h.length<2);)k=h[g][0]-f.position.left,l=h[g][1]-f.position.top,(b.x===L&&k>=i||b.x===N&&i>=k||b.x===O&&(i>k||k>f.width-i)||b.y===K&&l>=j||b.y===M&&j>=l||b.y===O&&(j>l||l>f.height-j))&&h.splice(g,1);f.position={left:h[0][0],top:h[0][1]}}return f},rect:function(a,b,c,d){return{width:Math.abs(c-a),height:Math.abs(d-b),position:{left:Math.min(a,c),top:Math.min(b,d)}}},_angles:{tc:1.5,tr:7/4,tl:5/4,bc:.5,br:.25,bl:.75,rc:2,lc:1,c:0},ellipse:function(a,b,c,d,e){var f=R.polys._angles[e.abbrev()],g=0===f?0:c*Math.cos(f*Math.PI),h=d*Math.sin(f*Math.PI);return{width:2*c-Math.abs(g),height:2*d-Math.abs(h),position:{left:a+g,top:b+h},adjustable:E}},circle:function(a,b,c,d){return R.polys.ellipse(a,b,c,c,d)}},R.svg=function(a,c,e){for(var f,g,h,i,j,k,l,m,n,o=c[0],p=d(o.ownerSVGElement),q=o.ownerDocument,r=(parseInt(c.css("stroke-width"),10)||0)/2;!o.getBBox;)o=o.parentNode;if(!o.getBBox||!o.parentNode)return E;switch(o.nodeName){case"ellipse":case"circle":m=R.polys.ellipse(o.cx.baseVal.value,o.cy.baseVal.value,(o.rx||o.r).baseVal.value+r,(o.ry||o.r).baseVal.value+r,e);break;case"line":case"polygon":case"polyline":for(l=o.points||[{x:o.x1.baseVal.value,y:o.y1.baseVal.value},{x:o.x2.baseVal.value,y:o.y2.baseVal.value}],m=[],k=-1,i=l.numberOfItems||l.length;++k';d.extend(x.prototype,{_scroll:function(){var b=this.qtip.elements.overlay;b&&(b[0].style.top=d(a).scrollTop()+"px")},init:function(c){var e=c.tooltip;d("select, object").length<1&&(this.bgiframe=c.elements.bgiframe=d(Ba).appendTo(e),c._bind(e,"tooltipmove",this.adjustBGIFrame,this._ns,this)),this.redrawContainer=d("
",{id:S+"-rcontainer"}).appendTo(b.body),c.elements.overlay&&c.elements.overlay.addClass("qtipmodal-ie6fix")&&(c._bind(a,["scroll","resize"],this._scroll,this._ns,this),c._bind(e,["tooltipshow"],this._scroll,this._ns,this)),this.redraw()},adjustBGIFrame:function(){var a,b,c=this.qtip.tooltip,d={height:c.outerHeight(E),width:c.outerWidth(E)},e=this.qtip.plugins.tip,f=this.qtip.elements.tip;b=parseInt(c.css("borderLeftWidth"),10)||0,b={left:-b,top:-b},e&&f&&(a="x"===e.corner.precedance?[I,L]:[J,K],b[a[1]]-=f[a[0]]()),this.bgiframe.css(b).css(d)},redraw:function(){if(this.qtip.rendered<1||this.drawing)return this;var a,b,c,d,e=this.qtip.tooltip,f=this.qtip.options.style,g=this.qtip.options.position.container;return this.qtip.drawing=1,f.height&&e.css(J,f.height),f.width?e.css(I,f.width):(e.css(I,"").appendTo(this.redrawContainer),b=e.width(),1>b%2&&(b+=1),c=e.css("maxWidth")||"",d=e.css("minWidth")||"",a=(c+d).indexOf("%")>-1?g.width()/100:0,c=(c.indexOf("%")>-1?a:1*parseInt(c,10))||b,d=(d.indexOf("%")>-1?a:1*parseInt(d,10))||0,b=c+d?Math.min(Math.max(b,d),c):b,e.css(I,Math.round(b)).appendTo(g)),this.drawing=0,this},destroy:function(){this.bgiframe&&this.bgiframe.remove(),this.qtip._unbind([a,this.qtip.tooltip],this._ns)}}),Aa=R.ie6=function(a){return 6===da.ie?new x(a):E},Aa.initialize="render",B.ie6={"^content|style$":function(){this.redraw()}}})}(window,document); +//# sourceMappingURL=jquery.qtip.min.map \ No newline at end of file diff --git a/src/assets/ext/jquery-ui/images/ui-bg_flat_0_aaaaaa_40x100.png b/assets/ext/jquery-ui/images/ui-bg_flat_0_aaaaaa_40x100.png similarity index 100% rename from src/assets/ext/jquery-ui/images/ui-bg_flat_0_aaaaaa_40x100.png rename to assets/ext/jquery-ui/images/ui-bg_flat_0_aaaaaa_40x100.png diff --git a/src/assets/ext/jquery-ui/images/ui-bg_flat_65_80e1ac_40x100.png b/assets/ext/jquery-ui/images/ui-bg_flat_65_80e1ac_40x100.png similarity index 100% rename from src/assets/ext/jquery-ui/images/ui-bg_flat_65_80e1ac_40x100.png rename to assets/ext/jquery-ui/images/ui-bg_flat_65_80e1ac_40x100.png diff --git a/src/assets/ext/jquery-ui/images/ui-bg_flat_75_3DD481_40x100.png b/assets/ext/jquery-ui/images/ui-bg_flat_75_3DD481_40x100.png similarity index 100% rename from src/assets/ext/jquery-ui/images/ui-bg_flat_75_3DD481_40x100.png rename to assets/ext/jquery-ui/images/ui-bg_flat_75_3DD481_40x100.png diff --git a/src/assets/ext/jquery-ui/images/ui-bg_flat_75_80e1ac_40x100.png b/assets/ext/jquery-ui/images/ui-bg_flat_75_80e1ac_40x100.png similarity index 100% rename from src/assets/ext/jquery-ui/images/ui-bg_flat_75_80e1ac_40x100.png rename to assets/ext/jquery-ui/images/ui-bg_flat_75_80e1ac_40x100.png diff --git a/src/assets/ext/jquery-ui/images/ui-bg_flat_75_ffffff_40x100.png b/assets/ext/jquery-ui/images/ui-bg_flat_75_ffffff_40x100.png similarity index 100% rename from src/assets/ext/jquery-ui/images/ui-bg_flat_75_ffffff_40x100.png rename to assets/ext/jquery-ui/images/ui-bg_flat_75_ffffff_40x100.png diff --git a/src/assets/ext/jquery-ui/images/ui-bg_flat_80_fcefa1_40x100.png b/assets/ext/jquery-ui/images/ui-bg_flat_80_fcefa1_40x100.png similarity index 100% rename from src/assets/ext/jquery-ui/images/ui-bg_flat_80_fcefa1_40x100.png rename to assets/ext/jquery-ui/images/ui-bg_flat_80_fcefa1_40x100.png diff --git a/src/assets/ext/jquery-ui/images/ui-bg_flat_95_f42727_40x100.png b/assets/ext/jquery-ui/images/ui-bg_flat_95_f42727_40x100.png similarity index 100% rename from src/assets/ext/jquery-ui/images/ui-bg_flat_95_f42727_40x100.png rename to assets/ext/jquery-ui/images/ui-bg_flat_95_f42727_40x100.png diff --git a/src/assets/ext/jquery-ui/images/ui-icons_062126_256x240.png b/assets/ext/jquery-ui/images/ui-icons_062126_256x240.png similarity index 100% rename from src/assets/ext/jquery-ui/images/ui-icons_062126_256x240.png rename to assets/ext/jquery-ui/images/ui-icons_062126_256x240.png diff --git a/src/assets/ext/jquery-ui/images/ui-icons_222222_256x240.png b/assets/ext/jquery-ui/images/ui-icons_222222_256x240.png similarity index 100% rename from src/assets/ext/jquery-ui/images/ui-icons_222222_256x240.png rename to assets/ext/jquery-ui/images/ui-icons_222222_256x240.png diff --git a/src/assets/ext/jquery-ui/images/ui-icons_ffffff_256x240.png b/assets/ext/jquery-ui/images/ui-icons_ffffff_256x240.png similarity index 100% rename from src/assets/ext/jquery-ui/images/ui-icons_ffffff_256x240.png rename to assets/ext/jquery-ui/images/ui-icons_ffffff_256x240.png diff --git a/assets/ext/jquery-ui/jquery-ui-timepicker-addon.min.js b/assets/ext/jquery-ui/jquery-ui-timepicker-addon.min.js new file mode 100644 index 00000000..d37bc02b --- /dev/null +++ b/assets/ext/jquery-ui/jquery-ui-timepicker-addon.min.js @@ -0,0 +1,2291 @@ +/*! jQuery Timepicker Addon - v1.6.3 - 2016-04-20 +* http://trentrichardson.com/examples/timepicker +* Copyright (c) 2016 Trent Richardson; Licensed MIT */ +(function (factory) { + if (typeof define === 'function' && define.amd) { + define(['jquery', 'jquery-ui'], factory); + } else { + factory(jQuery); + } +}(function ($) { + + /* + * Lets not redefine timepicker, Prevent "Uncaught RangeError: Maximum call stack size exceeded" + */ + $.ui.timepicker = $.ui.timepicker || {}; + if ($.ui.timepicker.version) { + return; + } + + /* + * Extend jQueryUI, get it started with our version number + */ + $.extend($.ui, { + timepicker: { + version: "1.6.3" + } + }); + + /* + * Timepicker manager. + * Use the singleton instance of this class, $.timepicker, to interact with the time picker. + * Settings for (groups of) time pickers are maintained in an instance object, + * allowing multiple different settings on the same page. + */ + var Timepicker = function () { + this.regional = []; // Available regional settings, indexed by language code + this.regional[''] = { // Default regional settings + currentText: 'Now', + closeText: 'Done', + amNames: ['AM', 'A'], + pmNames: ['PM', 'P'], + timeFormat: 'HH:mm', + timeSuffix: '', + timeOnlyTitle: 'Choose Time', + timeText: 'Time', + hourText: 'Hour', + minuteText: 'Minute', + secondText: 'Second', + millisecText: 'Millisecond', + microsecText: 'Microsecond', + timezoneText: 'Time Zone', + isRTL: false + }; + this._defaults = { // Global defaults for all the datetime picker instances + showButtonPanel: true, + timeOnly: false, + timeOnlyShowDate: false, + showHour: null, + showMinute: null, + showSecond: null, + showMillisec: null, + showMicrosec: null, + showTimezone: null, + showTime: true, + stepHour: 1, + stepMinute: 1, + stepSecond: 1, + stepMillisec: 1, + stepMicrosec: 1, + hour: 0, + minute: 0, + second: 0, + millisec: 0, + microsec: 0, + timezone: null, + hourMin: 0, + minuteMin: 0, + secondMin: 0, + millisecMin: 0, + microsecMin: 0, + hourMax: 23, + minuteMax: 59, + secondMax: 59, + millisecMax: 999, + microsecMax: 999, + minDateTime: null, + maxDateTime: null, + maxTime: null, + minTime: null, + onSelect: null, + hourGrid: 0, + minuteGrid: 0, + secondGrid: 0, + millisecGrid: 0, + microsecGrid: 0, + alwaysSetTime: true, + separator: ' ', + altFieldTimeOnly: true, + altTimeFormat: null, + altSeparator: null, + altTimeSuffix: null, + altRedirectFocus: true, + pickerTimeFormat: null, + pickerTimeSuffix: null, + showTimepicker: true, + timezoneList: null, + addSliderAccess: false, + sliderAccessArgs: null, + controlType: 'slider', + oneLine: false, + defaultValue: null, + parse: 'strict', + afterInject: null + }; + $.extend(this._defaults, this.regional['']); + }; + + $.extend(Timepicker.prototype, { + $input: null, + $altInput: null, + $timeObj: null, + inst: null, + hour_slider: null, + minute_slider: null, + second_slider: null, + millisec_slider: null, + microsec_slider: null, + timezone_select: null, + maxTime: null, + minTime: null, + hour: 0, + minute: 0, + second: 0, + millisec: 0, + microsec: 0, + timezone: null, + hourMinOriginal: null, + minuteMinOriginal: null, + secondMinOriginal: null, + millisecMinOriginal: null, + microsecMinOriginal: null, + hourMaxOriginal: null, + minuteMaxOriginal: null, + secondMaxOriginal: null, + millisecMaxOriginal: null, + microsecMaxOriginal: null, + ampm: '', + formattedDate: '', + formattedTime: '', + formattedDateTime: '', + timezoneList: null, + units: ['hour', 'minute', 'second', 'millisec', 'microsec'], + support: {}, + control: null, + + /* + * Override the default settings for all instances of the time picker. + * @param {Object} settings object - the new settings to use as defaults (anonymous object) + * @return {Object} the manager object + */ + setDefaults: function (settings) { + extendRemove(this._defaults, settings || {}); + return this; + }, + + /* + * Create a new Timepicker instance + */ + _newInst: function ($input, opts) { + var tp_inst = new Timepicker(), + inlineSettings = {}, + fns = {}, + overrides, i; + + for (var attrName in this._defaults) { + if (this._defaults.hasOwnProperty(attrName)) { + var attrValue = $input.attr('time:' + attrName); + if (attrValue) { + try { + inlineSettings[attrName] = eval(attrValue); + } catch (err) { + inlineSettings[attrName] = attrValue; + } + } + } + } + + overrides = { + beforeShow: function (input, dp_inst) { + if ($.isFunction(tp_inst._defaults.evnts.beforeShow)) { + return tp_inst._defaults.evnts.beforeShow.call($input[0], input, dp_inst, tp_inst); + } + }, + onChangeMonthYear: function (year, month, dp_inst) { + // Update the time as well : this prevents the time from disappearing from the $input field. + // tp_inst._updateDateTime(dp_inst); + if ($.isFunction(tp_inst._defaults.evnts.onChangeMonthYear)) { + tp_inst._defaults.evnts.onChangeMonthYear.call($input[0], year, month, dp_inst, tp_inst); + } + }, + onClose: function (dateText, dp_inst) { + if (tp_inst.timeDefined === true && $input.val() !== '') { + tp_inst._updateDateTime(dp_inst); + } + if ($.isFunction(tp_inst._defaults.evnts.onClose)) { + tp_inst._defaults.evnts.onClose.call($input[0], dateText, dp_inst, tp_inst); + } + } + }; + for (i in overrides) { + if (overrides.hasOwnProperty(i)) { + fns[i] = opts[i] || this._defaults[i] || null; + } + } + + tp_inst._defaults = $.extend({}, this._defaults, inlineSettings, opts, overrides, { + evnts: fns, + timepicker: tp_inst // add timepicker as a property of datepicker: $.datepicker._get(dp_inst, 'timepicker'); + }); + tp_inst.amNames = $.map(tp_inst._defaults.amNames, function (val) { + return val.toUpperCase(); + }); + tp_inst.pmNames = $.map(tp_inst._defaults.pmNames, function (val) { + return val.toUpperCase(); + }); + + // detect which units are supported + tp_inst.support = detectSupport( + tp_inst._defaults.timeFormat + + (tp_inst._defaults.pickerTimeFormat ? tp_inst._defaults.pickerTimeFormat : '') + + (tp_inst._defaults.altTimeFormat ? tp_inst._defaults.altTimeFormat : '')); + + // controlType is string - key to our this._controls + if (typeof(tp_inst._defaults.controlType) === 'string') { + if (tp_inst._defaults.controlType === 'slider' && typeof($.ui.slider) === 'undefined') { + tp_inst._defaults.controlType = 'select'; + } + tp_inst.control = tp_inst._controls[tp_inst._defaults.controlType]; + } + // controlType is an object and must implement create, options, value methods + else { + tp_inst.control = tp_inst._defaults.controlType; + } + + // prep the timezone options + var timezoneList = [-720, -660, -600, -570, -540, -480, -420, -360, -300, -270, -240, -210, -180, -120, -60, + 0, 60, 120, 180, 210, 240, 270, 300, 330, 345, 360, 390, 420, 480, 525, 540, 570, 600, 630, 660, 690, 720, 765, 780, 840]; + if (tp_inst._defaults.timezoneList !== null) { + timezoneList = tp_inst._defaults.timezoneList; + } + var tzl = timezoneList.length, tzi = 0, tzv = null; + if (tzl > 0 && typeof timezoneList[0] !== 'object') { + for (; tzi < tzl; tzi++) { + tzv = timezoneList[tzi]; + timezoneList[tzi] = { value: tzv, label: $.timepicker.timezoneOffsetString(tzv, tp_inst.support.iso8601) }; + } + } + tp_inst._defaults.timezoneList = timezoneList; + + // set the default units + tp_inst.timezone = tp_inst._defaults.timezone !== null ? $.timepicker.timezoneOffsetNumber(tp_inst._defaults.timezone) : + ((new Date()).getTimezoneOffset() * -1); + tp_inst.hour = tp_inst._defaults.hour < tp_inst._defaults.hourMin ? tp_inst._defaults.hourMin : + tp_inst._defaults.hour > tp_inst._defaults.hourMax ? tp_inst._defaults.hourMax : tp_inst._defaults.hour; + tp_inst.minute = tp_inst._defaults.minute < tp_inst._defaults.minuteMin ? tp_inst._defaults.minuteMin : + tp_inst._defaults.minute > tp_inst._defaults.minuteMax ? tp_inst._defaults.minuteMax : tp_inst._defaults.minute; + tp_inst.second = tp_inst._defaults.second < tp_inst._defaults.secondMin ? tp_inst._defaults.secondMin : + tp_inst._defaults.second > tp_inst._defaults.secondMax ? tp_inst._defaults.secondMax : tp_inst._defaults.second; + tp_inst.millisec = tp_inst._defaults.millisec < tp_inst._defaults.millisecMin ? tp_inst._defaults.millisecMin : + tp_inst._defaults.millisec > tp_inst._defaults.millisecMax ? tp_inst._defaults.millisecMax : tp_inst._defaults.millisec; + tp_inst.microsec = tp_inst._defaults.microsec < tp_inst._defaults.microsecMin ? tp_inst._defaults.microsecMin : + tp_inst._defaults.microsec > tp_inst._defaults.microsecMax ? tp_inst._defaults.microsecMax : tp_inst._defaults.microsec; + tp_inst.ampm = ''; + tp_inst.$input = $input; + + if (tp_inst._defaults.altField) { + tp_inst.$altInput = $(tp_inst._defaults.altField); + if (tp_inst._defaults.altRedirectFocus === true) { + tp_inst.$altInput.css({ + cursor: 'pointer' + }).focus(function () { + $input.trigger("focus"); + }); + } + } + + if (tp_inst._defaults.minDate === 0 || tp_inst._defaults.minDateTime === 0) { + tp_inst._defaults.minDate = new Date(); + } + if (tp_inst._defaults.maxDate === 0 || tp_inst._defaults.maxDateTime === 0) { + tp_inst._defaults.maxDate = new Date(); + } + + // datepicker needs minDate/maxDate, timepicker needs minDateTime/maxDateTime.. + if (tp_inst._defaults.minDate !== undefined && tp_inst._defaults.minDate instanceof Date) { + tp_inst._defaults.minDateTime = new Date(tp_inst._defaults.minDate.getTime()); + } + if (tp_inst._defaults.minDateTime !== undefined && tp_inst._defaults.minDateTime instanceof Date) { + tp_inst._defaults.minDate = new Date(tp_inst._defaults.minDateTime.getTime()); + } + if (tp_inst._defaults.maxDate !== undefined && tp_inst._defaults.maxDate instanceof Date) { + tp_inst._defaults.maxDateTime = new Date(tp_inst._defaults.maxDate.getTime()); + } + if (tp_inst._defaults.maxDateTime !== undefined && tp_inst._defaults.maxDateTime instanceof Date) { + tp_inst._defaults.maxDate = new Date(tp_inst._defaults.maxDateTime.getTime()); + } + tp_inst.$input.bind('focus', function () { + tp_inst._onFocus(); + }); + + return tp_inst; + }, + + /* + * add our sliders to the calendar + */ + _addTimePicker: function (dp_inst) { + var currDT = $.trim((this.$altInput && this._defaults.altFieldTimeOnly) ? this.$input.val() + ' ' + this.$altInput.val() : this.$input.val()); + + this.timeDefined = this._parseTime(currDT); + this._limitMinMaxDateTime(dp_inst, false); + this._injectTimePicker(); + this._afterInject(); + }, + + /* + * parse the time string from input value or _setTime + */ + _parseTime: function (timeString, withDate) { + if (!this.inst) { + this.inst = $.datepicker._getInst(this.$input[0]); + } + + if (withDate || !this._defaults.timeOnly) { + var dp_dateFormat = $.datepicker._get(this.inst, 'dateFormat'); + try { + var parseRes = parseDateTimeInternal(dp_dateFormat, this._defaults.timeFormat, timeString, $.datepicker._getFormatConfig(this.inst), this._defaults); + if (!parseRes.timeObj) { + return false; + } + $.extend(this, parseRes.timeObj); + } catch (err) { + $.timepicker.log("Error parsing the date/time string: " + err + + "\ndate/time string = " + timeString + + "\ntimeFormat = " + this._defaults.timeFormat + + "\ndateFormat = " + dp_dateFormat); + return false; + } + return true; + } else { + var timeObj = $.datepicker.parseTime(this._defaults.timeFormat, timeString, this._defaults); + if (!timeObj) { + return false; + } + $.extend(this, timeObj); + return true; + } + }, + + /* + * Handle callback option after injecting timepicker + */ + _afterInject: function() { + var o = this.inst.settings; + if ($.isFunction(o.afterInject)) { + o.afterInject.call(this); + } + }, + + /* + * generate and inject html for timepicker into ui datepicker + */ + _injectTimePicker: function () { + var $dp = this.inst.dpDiv, + o = this.inst.settings, + tp_inst = this, + litem = '', + uitem = '', + show = null, + max = {}, + gridSize = {}, + size = null, + i = 0, + l = 0; + + // Prevent displaying twice + if ($dp.find("div.ui-timepicker-div").length === 0 && o.showTimepicker) { + var noDisplay = ' ui_tpicker_unit_hide', + html = '
' + '
' + o.timeText + '
' + + '
'; + + // Create the markup + for (i = 0, l = this.units.length; i < l; i++) { + litem = this.units[i]; + uitem = litem.substr(0, 1).toUpperCase() + litem.substr(1); + show = o['show' + uitem] !== null ? o['show' + uitem] : this.support[litem]; + + // Added by Peter Medeiros: + // - Figure out what the hour/minute/second max should be based on the step values. + // - Example: if stepMinute is 15, then minMax is 45. + max[litem] = parseInt((o[litem + 'Max'] - ((o[litem + 'Max'] - o[litem + 'Min']) % o['step' + uitem])), 10); + gridSize[litem] = 0; + + html += '
' + o[litem + 'Text'] + '
' + + '
'; + + if (show && o[litem + 'Grid'] > 0) { + html += '
'; + + if (litem === 'hour') { + for (var h = o[litem + 'Min']; h <= max[litem]; h += parseInt(o[litem + 'Grid'], 10)) { + gridSize[litem]++; + var tmph = $.datepicker.formatTime(this.support.ampm ? 'hht' : 'HH', {hour: h}, o); + html += ''; + } + } + else { + for (var m = o[litem + 'Min']; m <= max[litem]; m += parseInt(o[litem + 'Grid'], 10)) { + gridSize[litem]++; + html += ''; + } + } + + html += '
' + tmph + '' + ((m < 10) ? '0' : '') + m + '
'; + } + html += '
'; + } + + // Timezone + var showTz = o.showTimezone !== null ? o.showTimezone : this.support.timezone; + html += '
' + o.timezoneText + '
'; + html += '
'; + + // Create the elements from string + html += '
'; + var $tp = $(html); + + // if we only want time picker... + if (o.timeOnly === true) { + $tp.prepend('
' + '
' + o.timeOnlyTitle + '
' + '
'); + $dp.find('.ui-datepicker-header, .ui-datepicker-calendar').hide(); + } + + // add sliders, adjust grids, add events + for (i = 0, l = tp_inst.units.length; i < l; i++) { + litem = tp_inst.units[i]; + uitem = litem.substr(0, 1).toUpperCase() + litem.substr(1); + show = o['show' + uitem] !== null ? o['show' + uitem] : this.support[litem]; + + // add the slider + tp_inst[litem + '_slider'] = tp_inst.control.create(tp_inst, $tp.find('.ui_tpicker_' + litem + '_slider'), litem, tp_inst[litem], o[litem + 'Min'], max[litem], o['step' + uitem]); + + // adjust the grid and add click event + if (show && o[litem + 'Grid'] > 0) { + size = 100 * gridSize[litem] * o[litem + 'Grid'] / (max[litem] - o[litem + 'Min']); + $tp.find('.ui_tpicker_' + litem + ' table').css({ + width: size + "%", + marginLeft: o.isRTL ? '0' : ((size / (-2 * gridSize[litem])) + "%"), + marginRight: o.isRTL ? ((size / (-2 * gridSize[litem])) + "%") : '0', + borderCollapse: 'collapse' + }).find("td").click(function (e) { + var $t = $(this), + h = $t.html(), + n = parseInt(h.replace(/[^0-9]/g), 10), + ap = h.replace(/[^apm]/ig), + f = $t.data('for'); // loses scope, so we use data-for + + if (f === 'hour') { + if (ap.indexOf('p') !== -1 && n < 12) { + n += 12; + } + else { + if (ap.indexOf('a') !== -1 && n === 12) { + n = 0; + } + } + } + + tp_inst.control.value(tp_inst, tp_inst[f + '_slider'], litem, n); + + tp_inst._onTimeChange(); + tp_inst._onSelectHandler(); + }).css({ + cursor: 'pointer', + width: (100 / gridSize[litem]) + '%', + textAlign: 'center', + overflow: 'hidden' + }); + } // end if grid > 0 + } // end for loop + + // Add timezone options + this.timezone_select = $tp.find('.ui_tpicker_timezone').append('').find("select"); + $.fn.append.apply(this.timezone_select, + $.map(o.timezoneList, function (val, idx) { + return $("
",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+k+"-]").length||v.push("~="),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+k+"+*").length||v.push(".#.+[+~]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",$)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e===C||e.ownerDocument===m&&y(m,e)?-1:t===C||t.ownerDocument===m&&y(m,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e===C?-1:t===C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]===m?-1:s[r]===m?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if((e.ownerDocument||e)!==C&&T(e),d.matchesSelector&&E&&!A[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){A(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=p[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&p(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?k.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?k.grep(e,function(e){return e===n!==r}):"string"!=typeof n?k.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(k.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||q,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:L.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof k?t[0]:t,k.merge(this,k.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),D.test(r[1])&&k.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(k):k.makeArray(e,this)}).prototype=k.fn,q=k(E);var H=/^(?:parents|prev(?:Until|All))/,O={children:!0,contents:!0,next:!0,prev:!0};function P(e,t){while((e=e[t])&&1!==e.nodeType);return e}k.fn.extend({has:function(e){var t=k(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i,ge={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?k.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;nx",y.noCloneChecked=!!me.cloneNode(!0).lastChild.defaultValue;var Te=/^key/,Ce=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ee=/^([^.]*)(?:\.(.+)|)/;function ke(){return!0}function Se(){return!1}function Ne(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function Ae(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Ae(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Se;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return k().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=k.guid++)),e.each(function(){k.event.add(this,t,i,r,n)})}function De(e,i,o){o?(Q.set(e,i,!1),k.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Q.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(k.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Q.set(this,i,r),t=o(this,i),this[i](),r!==(n=Q.get(this,i))||t?Q.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Q.set(this,i,{value:k.event.trigger(k.extend(r[0],k.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Q.get(e,i)&&k.event.add(e,i,ke)}k.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.get(t);if(v){n.handler&&(n=(o=n).handler,i=o.selector),i&&k.find.matchesSelector(ie,i),n.guid||(n.guid=k.guid++),(u=v.events)||(u=v.events={}),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof k&&k.event.triggered!==e.type?k.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(R)||[""]).length;while(l--)d=g=(s=Ee.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=k.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=k.event.special[d]||{},c=k.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&k.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),k.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Q.hasData(e)&&Q.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(R)||[""]).length;while(l--)if(d=g=(s=Ee.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=k.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||k.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)k.event.remove(e,d+t[l],n,r,!0);k.isEmptyObject(u)&&Q.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=k.event.fix(e),u=new Array(arguments.length),l=(Q.get(this,"events")||{})[s.type]||[],c=k.event.special[s.type]||{};for(u[0]=s,t=1;t\x20\t\r\n\f]*)[^>]*)\/>/gi,qe=/\s*$/g;function Oe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&k(e).children("tbody")[0]||e}function Pe(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function Re(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Me(e,t){var n,r,i,o,a,s,u,l;if(1===t.nodeType){if(Q.hasData(e)&&(o=Q.access(e),a=Q.set(t,o),l=o.events))for(i in delete a.handle,a.events={},l)for(n=0,r=l[i].length;n")},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=oe(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||k.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Vt,Gt=[],Yt=/(=)\?(?=&|$)|\?\?/;k.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Gt.pop()||k.expando+"_"+kt++;return this[e]=!0,e}}),k.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Yt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Yt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Yt,"$1"+r):!1!==e.jsonp&&(e.url+=(St.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||k.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?k(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Gt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Vt=E.implementation.createHTMLDocument("").body).innerHTML="
",2===Vt.childNodes.length),k.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=D.exec(e))?[t.createElement(i[1])]:(i=we([e],t,o),o&&o.length&&k(o).remove(),k.merge([],i.childNodes)));var r,i,o},k.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(k.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},k.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){k.fn[t]=function(e){return this.on(t,e)}}),k.expr.pseudos.animated=function(t){return k.grep(k.timers,function(e){return t===e.elem}).length},k.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=k.css(e,"position"),c=k(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=k.css(e,"top"),u=k.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,k.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},k.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){k.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===k.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===k.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=k(e).offset()).top+=k.css(e,"borderTopWidth",!0),i.left+=k.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-k.css(r,"marginTop",!0),left:t.left-i.left-k.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===k.css(e,"position"))e=e.offsetParent;return e||ie})}}),k.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;k.fn[t]=function(e){return _(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),k.each(["top","left"],function(e,n){k.cssHooks[n]=ze(y.pixelPosition,function(e,t){if(t)return t=_e(e,n),$e.test(t)?k(e).position()[n]+"px":t})}),k.each({Height:"height",Width:"width"},function(a,s){k.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){k.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return _(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?k.css(e,t,i):k.style(e,t,n,i)},s,n?e:void 0,n)}})}),k.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){k.fn[n]=function(e,t){return 0= 2.6.0. You are using Moment.js "+b.version+". See momentjs.com"),N.prototype={_set:function(c){this.name=c.name,this.abbrs=c.abbrs,this.untils=c.untils,this.offsets=c.offsets,this.population=c.population},_index:function(c){var M,A=+c,o=this.untils;for(M=0;M= 2.9.0. You are using Moment.js "+b.version+"."),b.defaultZone=c?s(c):null,b};var k=b.momentProperties;return"[object Array]"===Object.prototype.toString.call(k)?(k.push("_z"),k.push("_a")):k&&(k._z=null),m({version:"2019c",zones:["Africa/Abidjan|LMT GMT|g.8 0|01|-2ldXH.Q|48e5","Africa/Accra|LMT GMT +0020|.Q 0 -k|012121212121212121212121212121212121212121212121|-26BbX.8 6tzX.8 MnE 1BAk MnE 1BAk MnE 1BAk MnE 1C0k MnE 1BAk MnE 1BAk MnE 1BAk MnE 1C0k MnE 1BAk MnE 1BAk MnE 1BAk MnE 1C0k MnE 1BAk MnE 1BAk MnE 1BAk MnE 1C0k MnE 1BAk MnE 1BAk MnE 1BAk MnE 1C0k MnE 1BAk MnE 1BAk MnE|41e5","Africa/Nairobi|LMT EAT +0230 +0245|-2r.g -30 -2u -2J|01231|-1F3Cr.g 3Dzr.g okMu MFXJ|47e5","Africa/Algiers|PMT WET WEST CET CEST|-9.l 0 -10 -10 -20|0121212121212121343431312123431213|-2nco9.l cNb9.l HA0 19A0 1iM0 11c0 1oo0 Wo0 1rc0 QM0 1EM0 UM0 DA0 Imo0 rd0 De0 9Xz0 1fb0 1ap0 16K0 2yo0 mEp0 hwL0 jxA0 11A0 dDd0 17b0 11B0 1cN0 2Dy0 1cN0 1fB0 1cL0|26e5","Africa/Lagos|LMT WAT|-d.A -10|01|-22y0d.A|17e6","Africa/Bissau|LMT -01 GMT|12.k 10 0|012|-2ldX0 2xoo0|39e4","Africa/Maputo|LMT CAT|-2a.k -20|01|-2GJea.k|26e5","Africa/Cairo|EET EEST|-20 -30|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-1bIO0 vb0 1ip0 11z0 1iN0 1nz0 12p0 1pz0 10N0 1pz0 16p0 1jz0 s3d0 Vz0 1oN0 11b0 1oO0 10N0 1pz0 10N0 1pb0 10N0 1pb0 10N0 1pb0 10N0 1pz0 10N0 1pb0 10N0 1pb0 11d0 1oL0 11d0 1pb0 11d0 1oL0 11d0 1oL0 11d0 1oL0 11d0 1pb0 11d0 1oL0 11d0 1oL0 11d0 1oL0 11d0 1pb0 11d0 1oL0 11d0 1oL0 11d0 1oL0 11d0 1pb0 11d0 1oL0 11d0 1WL0 rd0 1Rz0 wp0 1pb0 11d0 1oL0 11d0 1oL0 11d0 1oL0 11d0 1pb0 11d0 1qL0 Xd0 1oL0 11d0 1oL0 11d0 1pb0 11d0 1oL0 11d0 1oL0 11d0 1ny0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 WL0 1qN0 Rb0 1wp0 On0 1zd0 Lz0 1EN0 Fb0 c10 8n0 8Nd0 gL0 e10 mn0|15e6","Africa/Casablanca|LMT +00 +01|u.k 0 -10|01212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212|-2gMnt.E 130Lt.E rb0 Dd0 dVb0 b6p0 TX0 EoB0 LL0 gnd0 rz0 43d0 AL0 1Nd0 XX0 1Cp0 pz0 dEp0 4mn0 SyN0 AL0 1Nd0 wn0 1FB0 Db0 1zd0 Lz0 1Nf0 wM0 co0 go0 1o00 s00 dA0 vc0 11A0 A00 e00 y00 11A0 uM0 e00 Dc0 11A0 s00 e00 IM0 WM0 mo0 gM0 LA0 WM0 jA0 e00 28M0 e00 2600 e00 28M0 e00 2600 gM0 2600 e00 28M0 e00 2600 gM0 2600 e00 28M0 e00 2600 e00 28M0 e00 2600 gM0 2600 e00 28M0 e00 2600 gM0 2600 e00 2600 gM0 2600 e00 28M0 e00 2600 gM0|32e5","Africa/Ceuta|WET WEST CET CEST|0 -10 -10 -20|010101010101010101010232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232|-25KN0 11z0 drd0 18p0 3HX0 17d0 1fz0 1a10 1io0 1a00 1y7o0 LL0 gnd0 rz0 43d0 AL0 1Nd0 XX0 1Cp0 pz0 dEp0 4VB0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|85e3","Africa/El_Aaiun|LMT -01 +00 +01|Q.M 10 0 -10|012323232323232323232323232323232323232323232323232323232323232323232323232323232323|-1rDz7.c 1GVA7.c 6L0 AL0 1Nd0 XX0 1Cp0 pz0 1cBB0 AL0 1Nd0 wn0 1FB0 Db0 1zd0 Lz0 1Nf0 wM0 co0 go0 1o00 s00 dA0 vc0 11A0 A00 e00 y00 11A0 uM0 e00 Dc0 11A0 s00 e00 IM0 WM0 mo0 gM0 LA0 WM0 jA0 e00 28M0 e00 2600 e00 28M0 e00 2600 gM0 2600 e00 28M0 e00 2600 gM0 2600 e00 28M0 e00 2600 e00 28M0 e00 2600 gM0 2600 e00 28M0 e00 2600 gM0 2600 e00 2600 gM0 2600 e00 28M0 e00 2600 gM0|20e4","Africa/Johannesburg|SAST SAST SAST|-1u -20 -30|012121|-2GJdu 1Ajdu 1cL0 1cN0 1cL0|84e5","Africa/Juba|LMT CAT CAST EAT|-26.s -20 -30 -30|01212121212121212121212121212121213|-1yW26.s 1zK06.s 16L0 1iN0 17b0 1jd0 17b0 1ip0 17z0 1i10 17X0 1hB0 18n0 1hd0 19b0 1gp0 19z0 1iN0 17b0 1ip0 17z0 1i10 18n0 1hd0 18L0 1gN0 19b0 1gp0 19z0 1iN0 17z0 1i10 17X0 yGd0|","Africa/Khartoum|LMT CAT CAST EAT|-2a.8 -20 -30 -30|012121212121212121212121212121212131|-1yW2a.8 1zK0a.8 16L0 1iN0 17b0 1jd0 17b0 1ip0 17z0 1i10 17X0 1hB0 18n0 1hd0 19b0 1gp0 19z0 1iN0 17b0 1ip0 17z0 1i10 18n0 1hd0 18L0 1gN0 19b0 1gp0 19z0 1iN0 17z0 1i10 17X0 yGd0 HjL0|51e5","Africa/Monrovia|MMT MMT GMT|H.8 I.u 0|012|-23Lzg.Q 28G01.m|11e5","Africa/Ndjamena|LMT WAT WAST|-10.c -10 -20|0121|-2le10.c 2J3c0.c Wn0|13e5","Africa/Sao_Tome|LMT GMT WAT|A.J 0 -10|0121|-2le00 4i6N0 2q00|","Africa/Tripoli|LMT CET CEST EET|-Q.I -10 -20 -20|012121213121212121212121213123123|-21JcQ.I 1hnBQ.I vx0 4iP0 xx0 4eN0 Bb0 7ip0 U0n0 A10 1db0 1cN0 1db0 1dd0 1db0 1eN0 1bb0 1e10 1cL0 1c10 1db0 1dd0 1db0 1cN0 1db0 1q10 fAn0 1ep0 1db0 AKq0 TA0 1o00|11e5","Africa/Tunis|PMT CET CEST|-9.l -10 -20|0121212121212121212121212121212121|-2nco9.l 18pa9.l 1qM0 DA0 3Tc0 11B0 1ze0 WM0 7z0 3d0 14L0 1cN0 1f90 1ar0 16J0 1gXB0 WM0 1rA0 11c0 nwo0 Ko0 1cM0 1cM0 1rA0 10M0 zuM0 10N0 1aN0 1qM0 WM0 1qM0 11A0 1o00|20e5","Africa/Windhoek|+0130 SAST SAST CAT WAT|-1u -20 -30 -20 -10|01213434343434343434343434343434343434343434343434343|-2GJdu 1Ajdu 1cL0 1SqL0 9Io0 16P0 1nX0 11B0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0|32e4","America/Adak|NST NWT NPT BST BDT AHST HST HDT|b0 a0 a0 b0 a0 a0 a0 90|012034343434343434343434343434343456767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676|-17SX0 8wW0 iB0 Qlb0 52O0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 cm0 10q0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|326","America/Anchorage|AST AWT APT AHST AHDT YST AKST AKDT|a0 90 90 a0 90 90 90 80|012034343434343434343434343434343456767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676|-17T00 8wX0 iA0 Qlb0 52O0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 cm0 10q0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|30e4","America/Port_of_Spain|LMT AST|46.4 40|01|-2kNvR.U|43e3","America/Araguaina|LMT -03 -02|3c.M 30 20|0121212121212121212121212121212121212121212121212121|-2glwL.c HdKL.c 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 1EN0 FX0 1HB0 Lz0 dMN0 Lz0 1zd0 Rb0 1wN0 Wn0 1tB0 Rb0 1tB0 WL0 1tB0 Rb0 1zd0 On0 1HB0 FX0 ny10 Lz0|14e4","America/Argentina/Buenos_Aires|CMT -04 -03 -02|4g.M 40 30 20|01212121212121212121212121212121212121212123232323232323232|-20UHH.c pKnH.c Mn0 1iN0 Tb0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 MN0 2jz0 MN0 4lX0 u10 5Lb0 1pB0 Fnz0 u10 uL0 1vd0 SL0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 zvd0 Bz0 1tB0 TX0 1wp0 Rb0 1wp0 Rb0 1wp0 TX0 A4p0 uL0 1qN0 WL0|","America/Argentina/Catamarca|CMT -04 -03 -02|4g.M 40 30 20|01212121212121212121212121212121212121212123232323132321232|-20UHH.c pKnH.c Mn0 1iN0 Tb0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 MN0 2jz0 MN0 4lX0 u10 5Lb0 1pB0 Fnz0 u10 uL0 1vd0 SL0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 zvd0 Bz0 1tB0 TX0 1wp0 Rb0 1wq0 Ra0 1wp0 TX0 rlB0 7B0 8zb0 uL0|","America/Argentina/Cordoba|CMT -04 -03 -02|4g.M 40 30 20|01212121212121212121212121212121212121212123232323132323232|-20UHH.c pKnH.c Mn0 1iN0 Tb0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 MN0 2jz0 MN0 4lX0 u10 5Lb0 1pB0 Fnz0 u10 uL0 1vd0 SL0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 zvd0 Bz0 1tB0 TX0 1wp0 Rb0 1wq0 Ra0 1wp0 TX0 A4p0 uL0 1qN0 WL0|","America/Argentina/Jujuy|CMT -04 -03 -02|4g.M 40 30 20|012121212121212121212121212121212121212121232323121323232|-20UHH.c pKnH.c Mn0 1iN0 Tb0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 MN0 2jz0 MN0 4lX0 u10 5Lb0 1pB0 Fnz0 u10 uL0 1vd0 SL0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 zvd0 Bz0 1tB0 TX0 1ze0 TX0 1ld0 WK0 1wp0 TX0 A4p0 uL0|","America/Argentina/La_Rioja|CMT -04 -03 -02|4g.M 40 30 20|012121212121212121212121212121212121212121232323231232321232|-20UHH.c pKnH.c Mn0 1iN0 Tb0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 MN0 2jz0 MN0 4lX0 u10 5Lb0 1pB0 Fnz0 u10 uL0 1vd0 SL0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 zvd0 Bz0 1tB0 TX0 1wp0 Qn0 qO0 16n0 Rb0 1wp0 TX0 rlB0 7B0 8zb0 uL0|","America/Argentina/Mendoza|CMT -04 -03 -02|4g.M 40 30 20|01212121212121212121212121212121212121212123232312121321232|-20UHH.c pKnH.c Mn0 1iN0 Tb0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 MN0 2jz0 MN0 4lX0 u10 5Lb0 1pB0 Fnz0 u10 uL0 1vd0 SL0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 zvd0 Bz0 1tB0 TX0 1u20 SL0 1vd0 Tb0 1wp0 TW0 ri10 Op0 7TX0 uL0|","America/Argentina/Rio_Gallegos|CMT -04 -03 -02|4g.M 40 30 20|01212121212121212121212121212121212121212123232323232321232|-20UHH.c pKnH.c Mn0 1iN0 Tb0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 MN0 2jz0 MN0 4lX0 u10 5Lb0 1pB0 Fnz0 u10 uL0 1vd0 SL0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 zvd0 Bz0 1tB0 TX0 1wp0 Rb0 1wp0 Rb0 1wp0 TX0 rlB0 7B0 8zb0 uL0|","America/Argentina/Salta|CMT -04 -03 -02|4g.M 40 30 20|012121212121212121212121212121212121212121232323231323232|-20UHH.c pKnH.c Mn0 1iN0 Tb0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 MN0 2jz0 MN0 4lX0 u10 5Lb0 1pB0 Fnz0 u10 uL0 1vd0 SL0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 zvd0 Bz0 1tB0 TX0 1wp0 Rb0 1wq0 Ra0 1wp0 TX0 A4p0 uL0|","America/Argentina/San_Juan|CMT -04 -03 -02|4g.M 40 30 20|012121212121212121212121212121212121212121232323231232321232|-20UHH.c pKnH.c Mn0 1iN0 Tb0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 MN0 2jz0 MN0 4lX0 u10 5Lb0 1pB0 Fnz0 u10 uL0 1vd0 SL0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 zvd0 Bz0 1tB0 TX0 1wp0 Qn0 qO0 16n0 Rb0 1wp0 TX0 rld0 m10 8lb0 uL0|","America/Argentina/San_Luis|CMT -04 -03 -02|4g.M 40 30 20|012121212121212121212121212121212121212121232323121212321212|-20UHH.c pKnH.c Mn0 1iN0 Tb0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 MN0 2jz0 MN0 4lX0 u10 5Lb0 1pB0 Fnz0 u10 uL0 1vd0 SL0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 zvd0 Bz0 1tB0 XX0 1q20 SL0 AN0 vDb0 m10 8lb0 8L0 jd0 1qN0 WL0 1qN0|","America/Argentina/Tucuman|CMT -04 -03 -02|4g.M 40 30 20|0121212121212121212121212121212121212121212323232313232123232|-20UHH.c pKnH.c Mn0 1iN0 Tb0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 MN0 2jz0 MN0 4lX0 u10 5Lb0 1pB0 Fnz0 u10 uL0 1vd0 SL0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 zvd0 Bz0 1tB0 TX0 1wp0 Rb0 1wq0 Ra0 1wp0 TX0 rlB0 4N0 8BX0 uL0 1qN0 WL0|","America/Argentina/Ushuaia|CMT -04 -03 -02|4g.M 40 30 20|01212121212121212121212121212121212121212123232323232321232|-20UHH.c pKnH.c Mn0 1iN0 Tb0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 1C10 LX0 1C10 LX0 1C10 LX0 1C10 Mn0 MN0 2jz0 MN0 4lX0 u10 5Lb0 1pB0 Fnz0 u10 uL0 1vd0 SL0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 zvd0 Bz0 1tB0 TX0 1wp0 Rb0 1wp0 Rb0 1wp0 TX0 rkN0 8p0 8zb0 uL0|","America/Curacao|LMT -0430 AST|4z.L 4u 40|012|-2kV7o.d 28KLS.d|15e4","America/Asuncion|AMT -04 -03|3O.E 40 30|012121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212|-1x589.k 1DKM9.k 3CL0 3Dd0 10L0 1pB0 10n0 1pB0 10n0 1pB0 1cL0 1dd0 1db0 1dd0 1cL0 1dd0 1cL0 1dd0 1cL0 1dd0 1db0 1dd0 1cL0 1dd0 1cL0 1dd0 1cL0 1dd0 1db0 1dd0 1cL0 1lB0 14n0 1dd0 1cL0 1fd0 WL0 1rd0 1aL0 1dB0 Xz0 1qp0 Xb0 1qN0 10L0 1rB0 TX0 1tB0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1qN0 1cL0 WN0 1qL0 11B0 1nX0 1ip0 WL0 1qN0 WL0 1qN0 WL0 1tB0 TX0 1tB0 TX0 1tB0 19X0 1a10 1fz0 1a10 1fz0 1cN0 17b0 1ip0 17b0 1ip0 17b0 1ip0 19X0 1fB0 19X0 1fB0 19X0 1ip0 17b0 1ip0 17b0 1ip0 19X0 1fB0 19X0 1fB0 19X0 1fB0 19X0 1ip0 17b0 1ip0 17b0 1ip0 19X0 1fB0 19X0 1fB0 19X0 1ip0 17b0 1ip0 17b0 1ip0 19X0 1fB0 19X0 1fB0 19X0 1fB0 19X0 1ip0 17b0 1ip0 17b0 1ip0|28e5","America/Atikokan|CST CDT CWT CPT EST|60 50 50 50 50|0101234|-25TQ0 1in0 Rnb0 3je0 8x30 iw0|28e2","America/Bahia_Banderas|LMT MST CST PST MDT CDT|71 70 60 80 60 50|0121212131414141414141414141414141414152525252525252525252525252525252525252525252525252525252|-1UQF0 deL0 8lc0 17c0 10M0 1dd0 otX0 gmN0 P2N0 13Vd0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 1fB0 WL0 1fB0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nW0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0|84e3","America/Bahia|LMT -03 -02|2y.4 30 20|01212121212121212121212121212121212121212121212121212121212121|-2glxp.U HdLp.U 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 1EN0 FX0 1HB0 Lz0 1EN0 Lz0 1C10 IL0 1HB0 Db0 1HB0 On0 1zd0 On0 1zd0 Lz0 1zd0 Rb0 1wN0 Wn0 1tB0 Rb0 1tB0 WL0 1tB0 Rb0 1zd0 On0 1HB0 FX0 l5B0 Rb0|27e5","America/Barbados|LMT BMT AST ADT|3W.t 3W.t 40 30|01232323232|-1Q0I1.v jsM0 1ODC1.v IL0 1ip0 17b0 1ip0 17b0 1ld0 13b0|28e4","America/Belem|LMT -03 -02|3d.U 30 20|012121212121212121212121212121|-2glwK.4 HdKK.4 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0|20e5","America/Belize|LMT CST -0530 CDT|5Q.M 60 5u 50|01212121212121212121212121212121212121212121212121213131|-2kBu7.c fPA7.c Onu 1zcu Rbu 1wou Rbu 1wou Rbu 1zcu Onu 1zcu Onu 1zcu Rbu 1wou Rbu 1wou Rbu 1wou Rbu 1zcu Onu 1zcu Onu 1zcu Rbu 1wou Rbu 1wou Rbu 1zcu Onu 1zcu Onu 1zcu Onu 1zcu Rbu 1wou Rbu 1wou Rbu 1zcu Onu 1zcu Onu 1zcu Rbu 1wou Rbu 1f0Mu qn0 lxB0 mn0|57e3","America/Blanc-Sablon|AST ADT AWT APT|40 30 30 30|010230|-25TS0 1in0 UGp0 8x50 iu0|11e2","America/Boa_Vista|LMT -04 -03|42.E 40 30|0121212121212121212121212121212121|-2glvV.k HdKV.k 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 smp0 WL0 1tB0 2L0|62e2","America/Bogota|BMT -05 -04|4U.g 50 40|0121|-2eb73.I 38yo3.I 2en0|90e5","America/Boise|PST PDT MST MWT MPT MDT|80 70 70 60 60 60|0101023425252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252|-261q0 1nX0 11B0 1nX0 8C10 JCL0 8x20 ix0 QwN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 Dd0 1Kn0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|21e4","America/Cambridge_Bay|-00 MST MWT MPT MDDT MDT CST CDT EST|0 70 60 60 50 60 60 50 50|0123141515151515151515151515151515151515151515678651515151515151515151515151515151515151515151515151515151515151515151515151|-21Jc0 RO90 8x20 ix0 LCL0 1fA0 zgO0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11A0 1nX0 2K0 WQ0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|15e2","America/Campo_Grande|LMT -04 -03|3C.s 40 30|01212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2glwl.w HdLl.w 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 1EN0 FX0 1HB0 Lz0 1EN0 Lz0 1C10 IL0 1HB0 Db0 1HB0 On0 1zd0 On0 1zd0 Lz0 1zd0 Rb0 1wN0 Wn0 1tB0 Rb0 1tB0 WL0 1tB0 Rb0 1zd0 On0 1HB0 FX0 1C10 Lz0 1Ip0 HX0 1zd0 On0 1HB0 IL0 1wp0 On0 1C10 Lz0 1C10 On0 1zd0 On0 1zd0 Rb0 1zd0 Lz0 1C10 Lz0 1C10 On0 1zd0 On0 1zd0 On0 1zd0 On0 1HB0 FX0|77e4","America/Cancun|LMT CST EST EDT CDT|5L.4 60 50 40 50|0123232341414141414141414141414141414141412|-1UQG0 2q2o0 yLB0 1lb0 14p0 1lb0 14p0 Lz0 xB0 14p0 1nX0 11B0 1nX0 1fB0 WL0 1fB0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 Dd0|63e4","America/Caracas|CMT -0430 -04|4r.E 4u 40|01212|-2kV7w.k 28KM2.k 1IwOu kqo0|29e5","America/Cayenne|LMT -04 -03|3t.k 40 30|012|-2mrwu.E 2gWou.E|58e3","America/Panama|CMT EST|5j.A 50|01|-2uduE.o|15e5","America/Chicago|CST CDT EST CWT CPT|60 50 50 50 50|01010101010101010101010101010101010102010101010103401010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-261s0 1nX0 11B0 1nX0 1wp0 TX0 WN0 1qL0 1cN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 11B0 1Hz0 14p0 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 RB0 8x30 iw0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|92e5","America/Chihuahua|LMT MST CST CDT MDT|74.k 70 60 50 60|0121212323241414141414141414141414141414141414141414141414141414141414141414141414141414141|-1UQF0 deL0 8lc0 17c0 10M0 1dd0 2zQN0 1lb0 14p0 1lb0 14q0 1lb0 14p0 1nX0 11B0 1nX0 1fB0 WL0 1fB0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0|81e4","America/Costa_Rica|SJMT CST CDT|5A.d 60 50|0121212121|-1Xd6n.L 2lu0n.L Db0 1Kp0 Db0 pRB0 15b0 1kp0 mL0|12e5","America/Creston|MST PST|70 80|010|-29DR0 43B0|53e2","America/Cuiaba|LMT -04 -03|3I.k 40 30|012121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2glwf.E HdLf.E 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 1EN0 FX0 1HB0 Lz0 1EN0 Lz0 1C10 IL0 1HB0 Db0 1HB0 On0 1zd0 On0 1zd0 Lz0 1zd0 Rb0 1wN0 Wn0 1tB0 Rb0 1tB0 WL0 1tB0 Rb0 1zd0 On0 1HB0 FX0 4a10 HX0 1zd0 On0 1HB0 IL0 1wp0 On0 1C10 Lz0 1C10 On0 1zd0 On0 1zd0 Rb0 1zd0 Lz0 1C10 Lz0 1C10 On0 1zd0 On0 1zd0 On0 1zd0 On0 1HB0 FX0|54e4","America/Danmarkshavn|LMT -03 -02 GMT|1e.E 30 20 0|01212121212121212121212121212121213|-2a5WJ.k 2z5fJ.k 19U0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 DC0|8","America/Dawson_Creek|PST PDT PWT PPT MST|80 70 70 70 70|0102301010101010101010101010101010101010101010101010101014|-25TO0 1in0 UGp0 8x10 iy0 3NB0 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 ML0|12e3","America/Dawson|YST YDT YWT YPT YDDT PST PDT|90 80 80 80 70 80 70|0101023040565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565|-25TN0 1in0 1o10 13V0 Ser0 8x00 iz0 LCL0 1fA0 jrA0 fNd0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|13e2","America/Denver|MST MDT MWT MPT|70 60 60 60|01010101023010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-261r0 1nX0 11B0 1nX0 11B0 1qL0 WN0 mn0 Ord0 8x20 ix0 LCN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|26e5","America/Detroit|LMT CST EST EWT EPT EDT|5w.b 60 50 40 40 40|0123425252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252|-2Cgir.N peqr.N 156L0 8x40 iv0 6fd0 11z0 JxX1 SMX 1cN0 1cL0 aW10 1cL0 s10 1Vz0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|37e5","America/Edmonton|LMT MST MDT MWT MPT|7x.Q 70 60 60 60|0121212121212134121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2yd4q.8 shdq.8 1in0 17d0 hz0 2dB0 1fz0 1a10 11z0 1qN0 WL0 1qN0 11z0 IGN0 8x20 ix0 3NB0 11z0 XQp0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|10e5","America/Eirunepe|LMT -05 -04|4D.s 50 40|0121212121212121212121212121212121|-2glvk.w HdLk.w 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 dPB0 On0 yTd0 d5X0|31e3","America/El_Salvador|LMT CST CDT|5U.M 60 50|012121|-1XiG3.c 2Fvc3.c WL0 1qN0 WL0|11e5","America/Tijuana|LMT MST PST PDT PWT PPT|7M.4 70 80 70 70 70|012123245232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232|-1UQE0 4PX0 8mM0 8lc0 SN0 1cL0 pHB0 83r0 zI0 5O10 1Rz0 cOO0 11A0 1o00 11A0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1o00 11A0 BUp0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 U10 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|20e5","America/Fort_Nelson|PST PDT PWT PPT MST|80 70 70 70 70|01023010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010104|-25TO0 1in0 UGp0 8x10 iy0 3NB0 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0|39e2","America/Fort_Wayne|CST CDT CWT CPT EST EDT|60 50 50 50 50 40|010101023010101010101010101040454545454545454545454545454545454545454545454545454545454545454545454|-261s0 1nX0 11B0 1nX0 QI10 Db0 RB0 8x30 iw0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 5Tz0 1o10 qLb0 1cL0 1cN0 1cL0 1qhd0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|","America/Fortaleza|LMT -03 -02|2y 30 20|0121212121212121212121212121212121212121|-2glxq HdLq 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 1EN0 FX0 1HB0 Lz0 nsp0 WL0 1tB0 5z0 2mN0 On0|34e5","America/Glace_Bay|LMT AST ADT AWT APT|3X.M 40 30 30 30|012134121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2IsI0.c CwO0.c 1in0 UGp0 8x50 iu0 iq10 11z0 Jg10 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|19e3","America/Godthab|LMT -03 -02|3q.U 30 20|0121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2a5Ux.4 2z5dx.4 19U0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|17e3","America/Goose_Bay|NST NDT NST NDT NWT NPT AST ADT ADDT|3u.Q 2u.Q 3u 2u 2u 2u 40 30 20|010232323232323245232323232323232323232323232323232323232326767676767676767676767676767676767676767676768676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676|-25TSt.8 1in0 DXb0 2HbX.8 WL0 1qN0 WL0 1qN0 WL0 1tB0 TX0 1tB0 WL0 1qN0 WL0 1qN0 7UHu itu 1tB0 WL0 1qN0 WL0 1qN0 WL0 1qN0 WL0 1tB0 WL0 1ld0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 S10 g0u 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14n1 1lb0 14p0 1nW0 11C0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zcX Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|76e2","America/Grand_Turk|KMT EST EDT AST|57.a 50 40 40|01212121212121212121212121212121212121212121212121212121212121212121212121232121212121212121212121212121212121212121|-2l1uQ.O 2HHBQ.O 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 5Ip0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|37e2","America/Guatemala|LMT CST CDT|62.4 60 50|0121212121|-24KhV.U 2efXV.U An0 mtd0 Nz0 ifB0 17b0 zDB0 11z0|13e5","America/Guayaquil|QMT -05 -04|5e 50 40|0121|-1yVSK 2uILK rz0|27e5","America/Guyana|LMT -0345 -03 -04|3Q.E 3J 30 40|0123|-2dvU7.k 2r6LQ.k Bxbf|80e4","America/Halifax|LMT AST ADT AWT APT|4e.o 40 30 30 30|0121212121212121212121212121212121212121212121212134121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2IsHJ.A xzzJ.A 1db0 3I30 1in0 3HX0 IL0 1E10 ML0 1yN0 Pb0 1Bd0 Mn0 1Bd0 Rz0 1w10 Xb0 1w10 LX0 1w10 Xb0 1w10 Lz0 1C10 Jz0 1E10 OL0 1yN0 Un0 1qp0 Xb0 1qp0 11X0 1w10 Lz0 1HB0 LX0 1C10 FX0 1w10 Xb0 1qp0 Xb0 1BB0 LX0 1td0 Xb0 1qp0 Xb0 Rf0 8x50 iu0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 3Qp0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 3Qp0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 6i10 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|39e4","America/Havana|HMT CST CDT|5t.A 50 40|012121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-1Meuu.o 72zu.o ML0 sld0 An0 1Nd0 Db0 1Nd0 An0 6Ep0 An0 1Nd0 An0 JDd0 Mn0 1Ap0 On0 1fd0 11X0 1qN0 WL0 1wp0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 14n0 1ld0 14L0 1kN0 15b0 1kp0 1cL0 1cN0 1fz0 1a10 1fz0 1fB0 11z0 14p0 1nX0 11B0 1nX0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 14n0 1ld0 14n0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 1a10 1in0 1a10 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1cM0 1cM0 1fA0 17c0 1o00 11A0 1qM0 11A0 1o00 11A0 1o00 14o0 1lc0 14o0 1lc0 11A0 6i00 Rc0 1wo0 U00 1tA0 Rc0 1wo0 U00 1wo0 U00 1zc0 U00 1qM0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0|21e5","America/Hermosillo|LMT MST CST PST MDT|7n.Q 70 60 80 60|0121212131414141|-1UQF0 deL0 8lc0 17c0 10M0 1dd0 otX0 gmN0 P2N0 13Vd0 1lb0 14p0 1lb0 14p0 1lb0|64e4","America/Indiana/Knox|CST CDT CWT CPT EST|60 50 50 50 50|0101023010101010101010101010101010101040101010101010101010101010101010101010101010101010141010101010101010101010101010101010101010101010101010101010101010|-261s0 1nX0 11B0 1nX0 SgN0 8x30 iw0 3NB0 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 1fz0 1cN0 1cL0 1cN0 11z0 1o10 11z0 1o10 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 3Cn0 8wp0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 z8o0 1o00 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|","America/Indiana/Marengo|CST CDT CWT CPT EST EDT|60 50 50 50 50 40|0101023010101010101010104545454545414545454545454545454545454545454545454545454545454545454545454545454|-261s0 1nX0 11B0 1nX0 SgN0 8x30 iw0 dyN0 11z0 6fd0 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 jrz0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1VA0 LA0 1BX0 1e6p0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|","America/Indiana/Petersburg|CST CDT CWT CPT EST EDT|60 50 50 50 50 40|01010230101010101010101010104010101010101010101010141014545454545454545454545454545454545454545454545454545454545454|-261s0 1nX0 11B0 1nX0 SgN0 8x30 iw0 njX0 WN0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 3Fb0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 19co0 1o00 Rd0 1zb0 Oo0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|","America/Indiana/Tell_City|CST CDT CWT CPT EST EDT|60 50 50 50 50 40|01010230101010101010101010401054541010101010101010101010101010101010101010101010101010101010101010|-261s0 1nX0 11B0 1nX0 SgN0 8x30 iw0 njX0 WN0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 8wn0 1cN0 1cL0 1cN0 1cK0 1cN0 1cL0 1qhd0 1o00 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|","America/Indiana/Vevay|CST CDT CWT CPT EST EDT|60 50 50 50 50 40|010102304545454545454545454545454545454545454545454545454545454545454545454545454|-261s0 1nX0 11B0 1nX0 SgN0 8x30 iw0 kPB0 Awn0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1lnd0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|","America/Indiana/Vincennes|CST CDT CWT CPT EST EDT|60 50 50 50 50 40|01010230101010101010101010101010454541014545454545454545454545454545454545454545454545454545454545454|-261s0 1nX0 11B0 1nX0 SgN0 8x30 iw0 1o10 11z0 g0p0 11z0 1o10 11z0 1qL0 WN0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 1fz0 1cN0 WL0 1qN0 1cL0 1cN0 1cL0 1cN0 caL0 1cL0 1cN0 1cL0 1qhd0 1o00 Rd0 1zb0 Oo0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|","America/Indiana/Winamac|CST CDT CWT CPT EST EDT|60 50 50 50 50 40|01010230101010101010101010101010101010454541054545454545454545454545454545454545454545454545454545454545454|-261s0 1nX0 11B0 1nX0 SgN0 8x30 iw0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 1fz0 1cN0 1cL0 1cN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 jrz0 1cL0 1cN0 1cL0 1qhd0 1o00 Rd0 1za0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|","America/Inuvik|-00 PST PDDT MST MDT|0 80 60 70 60|0121343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343|-FnA0 tWU0 1fA0 wPe0 2pz0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|35e2","America/Iqaluit|-00 EWT EPT EST EDDT EDT CST CDT|0 40 40 50 30 40 60 50|01234353535353535353535353535353535353535353567353535353535353535353535353535353535353535353535353535353535353535353535353|-16K00 7nX0 iv0 LCL0 1fA0 zgO0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11C0 1nX0 11A0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|67e2","America/Jamaica|KMT EST EDT|57.a 50 40|0121212121212121212121|-2l1uQ.O 2uM1Q.O 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0|94e4","America/Juneau|PST PWT PPT PDT YDT YST AKST AKDT|80 70 70 70 80 90 90 80|01203030303030303030303030403030356767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676|-17T20 8x10 iy0 Vo10 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cM0 1cM0 1cL0 1cN0 1fz0 1a10 1fz0 co0 10q0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|33e3","America/Kentucky/Louisville|CST CDT CWT CPT EST EDT|60 50 50 50 50 40|0101010102301010101010101010101010101454545454545414545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454|-261s0 1nX0 11B0 1nX0 3Fd0 Nb0 LPd0 11z0 RB0 8x30 iw0 1nX1 e0X 9vd0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 xz0 gso0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1VA0 LA0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|","America/Kentucky/Monticello|CST CDT CWT CPT EST EDT|60 50 50 50 50 40|0101023010101010101010101010101010101010101010101010101010101010101010101454545454545454545454545454545454545454545454545454545454545454545454545454|-261s0 1nX0 11B0 1nX0 SgN0 8x30 iw0 SWp0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11A0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|","America/La_Paz|CMT BST -04|4w.A 3w.A 40|012|-1x37r.o 13b0|19e5","America/Lima|LMT -05 -04|58.A 50 40|0121212121212121|-2tyGP.o 1bDzP.o zX0 1aN0 1cL0 1cN0 1cL0 1PrB0 zX0 1O10 zX0 6Gp0 zX0 98p0 zX0|11e6","America/Los_Angeles|PST PDT PWT PPT|80 70 70 70|010102301010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-261q0 1nX0 11B0 1nX0 SgN0 8x10 iy0 5Wp1 1VaX 3dA0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1a00 1fA0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|15e6","America/Maceio|LMT -03 -02|2m.Q 30 20|012121212121212121212121212121212121212121|-2glxB.8 HdLB.8 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 1EN0 FX0 1HB0 Lz0 dMN0 Lz0 8Q10 WL0 1tB0 5z0 2mN0 On0|93e4","America/Managua|MMT CST EST CDT|5J.c 60 50 50|0121313121213131|-1quie.M 1yAMe.M 4mn0 9Up0 Dz0 1K10 Dz0 s3F0 1KH0 DB0 9In0 k8p0 19X0 1o30 11y0|22e5","America/Manaus|LMT -04 -03|40.4 40 30|01212121212121212121212121212121|-2glvX.U HdKX.U 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 dPB0 On0|19e5","America/Martinique|FFMT AST ADT|44.k 40 30|0121|-2mPTT.E 2LPbT.E 19X0|39e4","America/Matamoros|LMT CST CDT|6E 60 50|0121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-1UQG0 2FjC0 1nX0 i6p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 1fB0 WL0 1fB0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 U10 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|45e4","America/Mazatlan|LMT MST CST PST MDT|75.E 70 60 80 60|0121212131414141414141414141414141414141414141414141414141414141414141414141414141414141414141|-1UQF0 deL0 8lc0 17c0 10M0 1dd0 otX0 gmN0 P2N0 13Vd0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 1fB0 WL0 1fB0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0|44e4","America/Menominee|CST CDT CWT CPT EST|60 50 50 50 50|01010230101041010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-261s0 1nX0 11B0 1nX0 SgN0 8x30 iw0 1o10 11z0 LCN0 1fz0 6410 9Jb0 1cM0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|85e2","America/Merida|LMT CST EST CDT|5W.s 60 50 50|0121313131313131313131313131313131313131313131313131313131313131313131313131313131313131|-1UQG0 2q2o0 2hz0 wu30 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 1fB0 WL0 1fB0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0|11e5","America/Metlakatla|PST PWT PPT PDT AKST AKDT|80 70 70 70 90 80|01203030303030303030303030303030304545450454545454545454545454545454545454545454|-17T20 8x10 iy0 Vo10 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1hU10 Rd0 1zb0 Op0 1zb0 Op0 1zb0 uM0 jB0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|14e2","America/Mexico_City|LMT MST CST CDT CWT|6A.A 70 60 50 50|012121232324232323232323232323232323232323232323232323232323232323232323232323232323232323232323232|-1UQF0 deL0 8lc0 17c0 10M0 1dd0 gEn0 TX0 3xd0 Jb0 6zB0 SL0 e5d0 17b0 1Pff0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 1fB0 WL0 1fB0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0|20e6","America/Miquelon|LMT AST -03 -02|3I.E 40 30 20|012323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232|-2mKkf.k 2LTAf.k gQ10 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|61e2","America/Moncton|EST AST ADT AWT APT|50 40 30 30 30|012121212121212121212134121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2IsH0 CwN0 1in0 zAo0 An0 1Nd0 An0 1Nd0 An0 1Nd0 An0 1Nd0 An0 1Nd0 An0 1K10 Lz0 1zB0 NX0 1u10 Wn0 S20 8x50 iu0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 3Cp0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14n1 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 ReX 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|64e3","America/Monterrey|LMT CST CDT|6F.g 60 50|0121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-1UQG0 2FjC0 1nX0 i6p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 1fB0 WL0 1fB0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0|41e5","America/Montevideo|LMT MMT -04 -03 -0330 -0230 -02 -0130|3I.P 3I.P 40 30 3u 2u 20 1u|012343434343434343434343435353636353636375363636363636363636363636363636363636363636363|-2tRUf.9 sVc0 8jcf.9 1db0 1dcu 1cLu 1dcu 1cLu ircu 11zu 1o0u 11zu 1o0u 11zu 1o0u 11zu 1qMu WLu 1qMu WLu 1fAu 1cLu 1o0u 11zu NAu 3jXu zXu Dq0u 19Xu pcu jz0 cm10 19X0 6tB0 1fbu 3o0u jX0 4vB0 xz0 3Cp0 mmu 1a10 IMu Db0 4c10 uL0 1Nd0 An0 1SN0 uL0 mp0 28L0 iPB0 un0 1SN0 xz0 1zd0 Lz0 1zd0 Rb0 1zd0 On0 1wp0 Rb0 s8p0 1fB0 1ip0 11z0 1ld0 14n0 1o10 11z0 1o10 11z0 1o10 14n0 1ld0 14n0 1ld0 14n0 1o10 11z0 1o10 11z0 1o10 11z0|17e5","America/Toronto|EST EDT EWT EPT|50 40 40 40|01010101010101010101010101010101010101010101012301010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-25TR0 1in0 11Wu 1nzu 1fD0 WJ0 1wr0 Nb0 1Ap0 On0 1zd0 On0 1wp0 TX0 1tB0 TX0 1tB0 TX0 1tB0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 4kM0 8x40 iv0 1o10 11z0 1nX0 11z0 1o10 11z0 1o10 1qL0 11D0 1nX0 11B0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|65e5","America/Nassau|LMT EST EDT|59.u 50 40|012121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2kNuO.u 26XdO.u 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|24e4","America/New_York|EST EDT EWT EPT|50 40 40 40|01010101010101010101010101010101010101010101010102301010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-261t0 1nX0 11B0 1nX0 11B0 1qL0 1a10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 RB0 8x40 iv0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|21e6","America/Nipigon|EST EDT EWT EPT|50 40 40 40|010123010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-25TR0 1in0 Rnb0 3je0 8x40 iv0 19yN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|16e2","America/Nome|NST NWT NPT BST BDT YST AKST AKDT|b0 a0 a0 b0 a0 90 90 80|012034343434343434343434343434343456767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676767676|-17SX0 8wW0 iB0 Qlb0 52O0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 cl0 10q0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|38e2","America/Noronha|LMT -02 -01|29.E 20 10|0121212121212121212121212121212121212121|-2glxO.k HdKO.k 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 1EN0 FX0 1HB0 Lz0 nsp0 WL0 1tB0 2L0 2pB0 On0|30e2","America/North_Dakota/Beulah|MST MDT MWT MPT CST CDT|70 60 60 60 60 50|010102301010101010101010101010101010101010101010101010101010101010101010101010101010101010101014545454545454545454545454545454545454545454545454545454|-261r0 1nX0 11B0 1nX0 SgN0 8x20 ix0 QwN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Oo0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|","America/North_Dakota/Center|MST MDT MWT MPT CST CDT|70 60 60 60 60 50|010102301010101010101010101010101010101010101010101010101014545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454|-261r0 1nX0 11B0 1nX0 SgN0 8x20 ix0 QwN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14o0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|","America/North_Dakota/New_Salem|MST MDT MWT MPT CST CDT|70 60 60 60 60 50|010102301010101010101010101010101010101010101010101010101010101010101010101010101454545454545454545454545454545454545454545454545454545454545454545454|-261r0 1nX0 11B0 1nX0 SgN0 8x20 ix0 QwN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14o0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|","America/Ojinaga|LMT MST CST CDT MDT|6V.E 70 60 50 60|0121212323241414141414141414141414141414141414141414141414141414141414141414141414141414141|-1UQF0 deL0 8lc0 17c0 10M0 1dd0 2zQN0 1lb0 14p0 1lb0 14q0 1lb0 14p0 1nX0 11B0 1nX0 1fB0 WL0 1fB0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 U10 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|23e3","America/Pangnirtung|-00 AST AWT APT ADDT ADT EDT EST CST CDT|0 40 30 30 20 30 40 50 60 50|012314151515151515151515151515151515167676767689767676767676767676767676767676767676767676767676767676767676767676767676767|-1XiM0 PnG0 8x50 iu0 LCL0 1fA0 zgO0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1o00 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11C0 1nX0 11A0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|14e2","America/Paramaribo|LMT PMT PMT -0330 -03|3E.E 3E.Q 3E.A 3u 30|01234|-2nDUj.k Wqo0.c qanX.I 1yVXN.o|24e4","America/Phoenix|MST MDT MWT|70 60 60|01010202010|-261r0 1nX0 11B0 1nX0 SgN0 4Al1 Ap0 1db0 SWqX 1cL0|42e5","America/Port-au-Prince|PPMT EST EDT|4N 50 40|01212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-28RHb 2FnMb 19X0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14q0 1o00 11A0 1o00 11A0 1o00 14o0 1lc0 14o0 1lc0 14o0 1o00 11A0 1o00 11A0 1o00 14o0 1lc0 14o0 1lc0 i6n0 1nX0 11B0 1nX0 d430 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 3iN0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|23e5","America/Rio_Branco|LMT -05 -04|4v.c 50 40|01212121212121212121212121212121|-2glvs.M HdLs.M 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 NBd0 d5X0|31e4","America/Porto_Velho|LMT -04 -03|4f.A 40 30|012121212121212121212121212121|-2glvI.o HdKI.o 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0|37e4","America/Puerto_Rico|AST AWT APT|40 30 30|0120|-17lU0 7XT0 iu0|24e5","America/Punta_Arenas|SMT -05 -04 -03|4G.K 50 40 30|0102021212121212121232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323|-2q2jh.e fJAh.e 5knG.K 1Vzh.e jRAG.K 1pbh.e 11d0 1oL0 11d0 1oL0 11d0 1oL0 11d0 1pb0 11d0 nHX0 op0 blz0 ko0 Qeo0 WL0 1zd0 On0 1ip0 11z0 1o10 11z0 1qN0 WL0 1ld0 14n0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 WL0 1qN0 1cL0 1cN0 11z0 1o10 11z0 1qN0 WL0 1fB0 19X0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 17b0 1ip0 11z0 1ip0 1fz0 1fB0 11z0 1qN0 WL0 1qN0 WL0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 17b0 1ip0 11z0 1o10 19X0 1fB0 1nX0 G10 1EL0 Op0 1zb0 Rd0 1wn0 Rd0 46n0 Ap0|","America/Rainy_River|CST CDT CWT CPT|60 50 50 50|010123010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-25TQ0 1in0 Rnb0 3je0 8x30 iw0 19yN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|842","America/Rankin_Inlet|-00 CST CDDT CDT EST|0 60 40 50 50|012131313131313131313131313131313131313131313431313131313131313131313131313131313131313131313131313131313131313131313131|-vDc0 keu0 1fA0 zgO0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|26e2","America/Recife|LMT -03 -02|2j.A 30 20|0121212121212121212121212121212121212121|-2glxE.o HdLE.o 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 1EN0 FX0 1HB0 Lz0 nsp0 WL0 1tB0 2L0 2pB0 On0|33e5","America/Regina|LMT MST MDT MWT MPT CST|6W.A 70 60 60 60 60|012121212121212121212121341212121212121212121212121215|-2AD51.o uHe1.o 1in0 s2L0 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 66N0 1cL0 1cN0 19X0 1fB0 1cL0 1fB0 1cL0 1cN0 1cL0 M30 8x20 ix0 1ip0 1cL0 1ip0 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 3NB0 1cL0 1cN0|19e4","America/Resolute|-00 CST CDDT CDT EST|0 60 40 50 50|012131313131313131313131313131313131313131313431313131313431313131313131313131313131313131313131313131313131313131313131|-SnA0 GWS0 1fA0 zgO0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|229","America/Santarem|LMT -04 -03|3C.M 40 30|0121212121212121212121212121212|-2glwl.c HdLl.c 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 qe10 xb0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 NBd0|21e4","America/Santiago|SMT -05 -04 -03|4G.K 50 40 30|010202121212121212321232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323|-2q2jh.e fJAh.e 5knG.K 1Vzh.e jRAG.K 1pbh.e 11d0 1oL0 11d0 1oL0 11d0 1oL0 11d0 1pb0 11d0 nHX0 op0 9Bz0 jb0 1oN0 ko0 Qeo0 WL0 1zd0 On0 1ip0 11z0 1o10 11z0 1qN0 WL0 1ld0 14n0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 WL0 1qN0 1cL0 1cN0 11z0 1o10 11z0 1qN0 WL0 1fB0 19X0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 17b0 1ip0 11z0 1ip0 1fz0 1fB0 11z0 1qN0 WL0 1qN0 WL0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 17b0 1ip0 11z0 1o10 19X0 1fB0 1nX0 G10 1EL0 Op0 1zb0 Rd0 1wn0 Rd0 46n0 Ap0 1Nb0 Ap0 1Nb0 Ap0 1zb0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 11B0 1nX0 11B0|62e5","America/Santo_Domingo|SDMT EST EDT -0430 AST|4E 50 40 4u 40|01213131313131414|-1ttjk 1lJMk Mn0 6sp0 Lbu 1Cou yLu 1RAu wLu 1QMu xzu 1Q0u xXu 1PAu 13jB0 e00|29e5","America/Sao_Paulo|LMT -03 -02|36.s 30 20|01212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2glwR.w HdKR.w 1cc0 1e10 1bX0 Ezd0 So0 1vA0 Mn0 1BB0 ML0 1BB0 zX0 pTd0 PX0 2ep0 nz0 1C10 zX0 1C10 LX0 1C10 Mn0 H210 Rb0 1tB0 IL0 1Fd0 FX0 1EN0 FX0 1HB0 Lz0 1EN0 Lz0 1C10 IL0 1HB0 Db0 1HB0 On0 1zd0 On0 1zd0 Lz0 1zd0 Rb0 1wN0 Wn0 1tB0 Rb0 1tB0 WL0 1tB0 Rb0 1zd0 On0 1HB0 FX0 1C10 Lz0 1Ip0 HX0 1zd0 On0 1HB0 IL0 1wp0 On0 1C10 Lz0 1C10 On0 1zd0 On0 1zd0 Rb0 1zd0 Lz0 1C10 Lz0 1C10 On0 1zd0 On0 1zd0 On0 1zd0 On0 1HB0 FX0|20e6","America/Scoresbysund|LMT -02 -01 +00|1r.Q 20 10 0|0121323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232|-2a5Ww.8 2z5ew.8 1a00 1cK0 1cL0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|452","America/Sitka|PST PWT PPT PDT YST AKST AKDT|80 70 70 70 90 90 80|01203030303030303030303030303030345656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565|-17T20 8x10 iy0 Vo10 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 co0 10q0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|90e2","America/St_Johns|NST NDT NST NDT NWT NPT NDDT|3u.Q 2u.Q 3u 2u 2u 2u 1u|01010101010101010101010101010101010102323232323232324523232323232323232323232323232323232323232323232323232323232323232323232323232323232326232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232|-28oit.8 14L0 1nB0 1in0 1gm0 Dz0 1JB0 1cL0 1cN0 1cL0 1fB0 19X0 1fB0 19X0 1fB0 19X0 1fB0 19X0 1fB0 1cL0 1cN0 1cL0 1fB0 19X0 1fB0 19X0 1fB0 19X0 1fB0 19X0 1fB0 1cL0 1fB0 19X0 1fB0 19X0 10O0 eKX.8 19X0 1iq0 WL0 1qN0 WL0 1qN0 WL0 1tB0 TX0 1tB0 WL0 1qN0 WL0 1qN0 7UHu itu 1tB0 WL0 1qN0 WL0 1qN0 WL0 1qN0 WL0 1tB0 WL0 1ld0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14n1 1lb0 14p0 1nW0 11C0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zcX Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|11e4","America/Swift_Current|LMT MST MDT MWT MPT CST|7b.k 70 60 60 60 60|012134121212121212121215|-2AD4M.E uHdM.E 1in0 UGp0 8x20 ix0 1o10 17b0 1ip0 11z0 1o10 11z0 1o10 11z0 isN0 1cL0 3Cp0 1cL0 1cN0 11z0 1qN0 WL0 pMp0|16e3","America/Tegucigalpa|LMT CST CDT|5M.Q 60 50|01212121|-1WGGb.8 2ETcb.8 WL0 1qN0 WL0 GRd0 AL0|11e5","America/Thule|LMT AST ADT|4z.8 40 30|012121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2a5To.Q 31NBo.Q 1cL0 1cN0 1cL0 1fB0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|656","America/Thunder_Bay|CST EST EWT EPT EDT|60 50 40 40 40|0123141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141|-2q5S0 1iaN0 8x40 iv0 XNB0 1cL0 1cN0 1fz0 1cN0 1cL0 3Cp0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|11e4","America/Vancouver|PST PDT PWT PPT|80 70 70 70|0102301010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-25TO0 1in0 UGp0 8x10 iy0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|23e5","America/Whitehorse|YST YDT YWT YPT YDDT PST PDT|90 80 80 80 70 80 70|0101023040565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565656565|-25TN0 1in0 1o10 13V0 Ser0 8x00 iz0 LCL0 1fA0 3NA0 vrd0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|23e3","America/Winnipeg|CST CDT CWT CPT|60 50 50 50|010101023010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2aIi0 WL0 3ND0 1in0 Jap0 Rb0 aCN0 8x30 iw0 1tB0 11z0 1ip0 11z0 1o10 11z0 1o10 11z0 1rd0 10L0 1op0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 1cL0 1cN0 11z0 6i10 WL0 6i10 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1a00 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1a00 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 14o0 1lc0 14o0 1o00 11A0 1o00 11A0 1o00 14o0 1lc0 14o0 1lc0 14o0 1o00 11A0 1o00 11A0 1o00 14o0 1lc0 14o0 1lc0 14o0 1lc0 14o0 1o00 11A0 1o00 11A0 1o00 14o0 1lc0 14o0 1lc0 14o0 1o00 11A0 1o00 11A0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|66e4","America/Yakutat|YST YWT YPT YDT AKST AKDT|90 80 80 80 90 80|01203030303030303030303030303030304545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454|-17T10 8x00 iz0 Vo10 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 cn0 10q0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|642","America/Yellowknife|-00 MST MWT MPT MDDT MDT|0 70 60 60 50 60|012314151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151|-1pdA0 hix0 8x20 ix0 LCL0 1fA0 zgO0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|19e3","Antarctica/Casey|-00 +08 +11|0 -80 -b0|01212121|-2q00 1DjS0 T90 40P0 KL0 blz0 3m10|10","Antarctica/Davis|-00 +07 +05|0 -70 -50|01012121|-vyo0 iXt0 alj0 1D7v0 VB0 3Wn0 KN0|70","Antarctica/DumontDUrville|-00 +10|0 -a0|0101|-U0o0 cfq0 bFm0|80","Antarctica/Macquarie|AEST AEDT -00 +11|-a0 -b0 0 -b0|0102010101010101010101010101010101010101010101010101010101010101010101010101010101010101013|-29E80 19X0 4SL0 1ayy0 Lvs0 1cM0 1o00 Rc0 1wo0 Rc0 1wo0 U00 1wo0 LA0 1C00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 11A0 1qM0 WM0 1qM0 Oo0 1zc0 Oo0 1zc0 Oo0 1wo0 WM0 1tA0 WM0 1tA0 U00 1tA0 U00 1tA0 11A0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 11A0 1o00 1io0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1cM0 1a00 1io0 1cM0 1cM0 1cM0 1cM0 1cM0|1","Antarctica/Mawson|-00 +06 +05|0 -60 -50|012|-CEo0 2fyk0|60","Pacific/Auckland|NZMT NZST NZST NZDT|-bu -cu -c0 -d0|01020202020202020202020202023232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323|-1GCVu Lz0 1tB0 11zu 1o0u 11zu 1o0u 11zu 1o0u 14nu 1lcu 14nu 1lcu 1lbu 11Au 1nXu 11Au 1nXu 11Au 1nXu 11Au 1nXu 11Au 1qLu WMu 1qLu 11Au 1n1bu IM0 1C00 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1qM0 14o0 1lc0 14o0 1lc0 14o0 1lc0 17c0 1io0 17c0 1io0 17c0 1io0 17c0 1lc0 14o0 1lc0 14o0 1lc0 17c0 1io0 17c0 1io0 17c0 1lc0 14o0 1lc0 14o0 1lc0 17c0 1io0 17c0 1io0 17c0 1io0 17c0 1io0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1io0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00|14e5","Antarctica/Palmer|-00 -03 -04 -02|0 30 40 20|0121212121213121212121212121212121212121212121212121212121212121212121212121212121|-cao0 nD0 1vd0 SL0 1vd0 17z0 1cN0 1fz0 1cN0 1cL0 1cN0 asn0 Db0 jsN0 14N0 11z0 1o10 11z0 1qN0 WL0 1qN0 WL0 1qN0 1cL0 1cN0 11z0 1o10 11z0 1qN0 WL0 1fB0 19X0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 17b0 1ip0 11z0 1ip0 1fz0 1fB0 11z0 1qN0 WL0 1qN0 WL0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 17b0 1ip0 11z0 1o10 19X0 1fB0 1nX0 G10 1EL0 Op0 1zb0 Rd0 1wn0 Rd0 46n0 Ap0|40","Antarctica/Rothera|-00 -03|0 30|01|gOo0|130","Antarctica/Syowa|-00 +03|0 -30|01|-vs00|20","Antarctica/Troll|-00 +00 +02|0 0 -20|01212121212121212121212121212121212121212121212121212121212121212121|1puo0 hd0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|40","Antarctica/Vostok|-00 +06|0 -60|01|-tjA0|25","Europe/Oslo|CET CEST|-10 -20|010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2awM0 Qm0 W6o0 5pf0 WM0 1fA0 1cM0 1cM0 1cM0 1cM0 wJc0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1qM0 WM0 zpc0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|62e4","Asia/Riyadh|LMT +03|-36.Q -30|01|-TvD6.Q|57e5","Asia/Almaty|LMT +05 +06 +07|-57.M -50 -60 -70|012323232323232323232321232323232323232323232323232|-1Pc57.M eUo7.M 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 IM0 rX0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0|15e5","Asia/Amman|LMT EET EEST|-2n.I -20 -30|0121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-1yW2n.I 1HiMn.I KL0 1oN0 11b0 1oN0 11b0 1pd0 1dz0 1cp0 11b0 1op0 11b0 fO10 1db0 1e10 1cL0 1cN0 1cL0 1cN0 1fz0 1pd0 10n0 1ld0 14n0 1hB0 15b0 1ip0 19X0 1cN0 1cL0 1cN0 17b0 1ld0 14o0 1lc0 17c0 1io0 17c0 1io0 17c0 1So0 y00 1fc0 1dc0 1co0 1dc0 1cM0 1cM0 1cM0 1o00 11A0 1lc0 17c0 1cM0 1cM0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 4bX0 Dd0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0|25e5","Asia/Anadyr|LMT +12 +13 +14 +11|-bN.U -c0 -d0 -e0 -b0|01232121212121212121214121212121212121212121212121212121212141|-1PcbN.U eUnN.U 23CL0 1db0 2q10 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 IM0 rX0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 2sp0 WM0|13e3","Asia/Aqtau|LMT +04 +05 +06|-3l.4 -40 -50 -60|012323232323232323232123232312121212121212121212|-1Pc3l.4 eUnl.4 24PX0 2pX0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 IM0 rX0 1cM0 1cM0 1cM0 1cM0 1cM0 1cN0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0|15e4","Asia/Aqtobe|LMT +04 +05 +06|-3M.E -40 -50 -60|0123232323232323232321232323232323232323232323232|-1Pc3M.E eUnM.E 23CL0 3Db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 IM0 rX0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0|27e4","Asia/Ashgabat|LMT +04 +05 +06|-3R.w -40 -50 -60|0123232323232323232323212|-1Pc3R.w eUnR.w 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 IM0|41e4","Asia/Atyrau|LMT +03 +05 +06 +04|-3r.I -30 -50 -60 -40|01232323232323232323242323232323232324242424242|-1Pc3r.I eUor.I 24PW0 2pX0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 IM0 rX0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 2sp0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0|","Asia/Baghdad|BMT +03 +04|-2V.A -30 -40|012121212121212121212121212121212121212121212121212121|-26BeV.A 2ACnV.A 11b0 1cp0 1dz0 1dd0 1db0 1cN0 1cp0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1de0 1dc0 1dc0 1dc0 1cM0 1dc0 1cM0 1dc0 1cM0 1dc0 1dc0 1dc0 1cM0 1dc0 1cM0 1dc0 1cM0 1dc0 1dc0 1dc0 1cM0 1dc0 1cM0 1dc0 1cM0 1dc0 1dc0 1dc0 1cM0 1dc0 1cM0 1dc0 1cM0 1dc0|66e5","Asia/Qatar|LMT +04 +03|-3q.8 -40 -30|012|-21Jfq.8 27BXq.8|96e4","Asia/Baku|LMT +03 +04 +05|-3j.o -30 -40 -50|01232323232323232323232123232323232323232323232323232323232323232|-1Pc3j.o 1jUoj.o WCL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 1cM0 9Je0 1o00 11z0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00|27e5","Asia/Bangkok|BMT +07|-6G.4 -70|01|-218SG.4|15e6","Asia/Barnaul|LMT +06 +07 +08|-5z -60 -70 -80|0123232323232323232323212323232321212121212121212121212121212121212|-21S5z pCnz 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 IM0 rX0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 p90 LE0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0 3rd0|","Asia/Beirut|EET EEST|-20 -30|010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-21aq0 1on0 1410 1db0 19B0 1in0 1ip0 WL0 1lQp0 11b0 1oN0 11b0 1oN0 11b0 1pd0 11b0 1oN0 11b0 q6N0 En0 1oN0 11b0 1oN0 11b0 1oN0 11b0 1pd0 11b0 1oN0 11b0 1op0 11b0 dA10 17b0 1iN0 17b0 1iN0 17b0 1iN0 17b0 1vB0 SL0 1mp0 13z0 1iN0 17b0 1iN0 17b0 1jd0 12n0 1a10 1cL0 1cN0 1cL0 1cN0 1cL0 1fB0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0|22e5","Asia/Bishkek|LMT +05 +06 +07|-4W.o -50 -60 -70|012323232323232323232321212121212121212121212121212|-1Pc4W.o eUnW.o 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2e00 1tX0 17b0 1ip0 17b0 1ip0 17b0 1ip0 17b0 1ip0 19X0 1cPu 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0|87e4","Asia/Brunei|LMT +0730 +08|-7D.E -7u -80|012|-1KITD.E gDc9.E|42e4","Asia/Kolkata|MMT IST +0630|-5l.a -5u -6u|012121|-2zOtl.a 1r2LP.a 1un0 HB0 7zX0|15e6","Asia/Chita|LMT +08 +09 +10|-7x.Q -80 -90 -a0|012323232323232323232321232323232323232323232323232323232323232312|-21Q7x.Q pAnx.Q 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 IM0 rX0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0 3re0|33e4","Asia/Choibalsan|LMT +07 +08 +10 +09|-7C -70 -80 -a0 -90|0123434343434343434343434343434343434343434343424242|-2APHC 2UkoC cKn0 1da0 1dd0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1fB0 1cL0 1cN0 1cL0 1cN0 1cL0 6hD0 11z0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 3Db0 h1f0 1cJ0 1cP0 1cJ0|38e3","Asia/Shanghai|CST CDT|-80 -90|010101010101010101010101010|-1c2w0 Rz0 11d0 1wL0 A10 8HX0 1G10 Tz0 1ip0 1jX0 1cN0 11b0 1oN0 aL0 1tU30 Rb0 1o10 11z0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0|23e6","Asia/Colombo|MMT +0530 +06 +0630|-5j.w -5u -60 -6u|01231321|-2zOtj.w 1rFbN.w 1zzu 7Apu 23dz0 11zu n3cu|22e5","Asia/Dhaka|HMT +0630 +0530 +06 +07|-5R.k -6u -5u -60 -70|0121343|-18LFR.k 1unn.k HB0 m6n0 2kxbu 1i00|16e6","Asia/Damascus|LMT EET EEST|-2p.c -20 -30|01212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-21Jep.c Hep.c 17b0 1ip0 17b0 1ip0 17b0 1ip0 19X0 1xRB0 11X0 1oN0 10L0 1pB0 11b0 1oN0 10L0 1mp0 13X0 1oN0 11b0 1pd0 11b0 1oN0 11b0 1oN0 11b0 1oN0 11b0 1pd0 11b0 1oN0 11b0 1oN0 11b0 1oN0 11b0 1pd0 11b0 1oN0 Nb0 1AN0 Nb0 bcp0 19X0 1gp0 19X0 3ld0 1xX0 Vd0 1Bz0 Sp0 1vX0 10p0 1dz0 1cN0 1cL0 1db0 1db0 1g10 1an0 1ap0 1db0 1fd0 1db0 1cN0 1db0 1dd0 1db0 1cp0 1dz0 1c10 1dX0 1cN0 1db0 1dd0 1db0 1cN0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1db0 1cN0 1db0 1cN0 19z0 1fB0 1qL0 11B0 1on0 Wp0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0|26e5","Asia/Dili|LMT +08 +09|-8m.k -80 -90|01212|-2le8m.k 1dnXm.k 1nfA0 Xld0|19e4","Asia/Dubai|LMT +04|-3F.c -40|01|-21JfF.c|39e5","Asia/Dushanbe|LMT +05 +06 +07|-4z.c -50 -60 -70|012323232323232323232321|-1Pc4z.c eUnz.c 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2hB0|76e4","Asia/Famagusta|LMT EET EEST +03|-2f.M -20 -30 -30|0121212121212121212121212121212121212121212121212121212121212121212121212121212121212312121212121212121212121212121212121212121|-1Vc2f.M 2a3cf.M 1cL0 1qp0 Xz0 19B0 19X0 1fB0 1db0 1cp0 1cL0 1fB0 19X0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1fB0 1cL0 1cN0 1cL0 1cN0 1o30 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 15U0 2Ks0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|","Asia/Gaza|EET EEST IST IDT|-20 -30 -20 -30|0101010101010101010101010101010123232323232323232323232323232320101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-1c2q0 5Rb0 10r0 1px0 10N0 1pz0 16p0 1jB0 16p0 1jx0 pBd0 Vz0 1oN0 11b0 1oO0 10N0 1pz0 10N0 1pb0 10N0 1pb0 10N0 1pb0 10N0 1pz0 10N0 1pb0 10N0 1pb0 11d0 1oL0 dW0 hfB0 Db0 1fB0 Rb0 bXd0 gM0 8Q00 IM0 1wM0 11z0 1C10 IL0 1s10 10n0 1o10 WL0 1zd0 On0 1ld0 11z0 1o10 14n0 1o10 14n0 1nd0 12n0 1nd0 Xz0 1q10 12n0 M10 C00 17c0 1io0 17c0 1io0 17c0 1o00 1cL0 1fB0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 17c0 1io0 18N0 1bz0 19z0 1gp0 1610 1iL0 11z0 1o10 14o0 1lA1 SKX 1xd1 MKX 1AN0 1a00 1fA0 1cL0 1cN0 1nX0 1210 1nz0 1220 1qL0 WN0 1qL0 WN0 1qL0 11c0 1oo0 11c0 1rc0 Wo0 1rc0 Wo0 1rc0 11c0 1oo0 11c0 1oo0 11c0 1oo0 11c0 1rc0 Wo0 1rc0 11c0 1oo0 11c0 1oo0 11c0 1oo0 11c0 1oo0 11c0 1rc0 Wo0 1rc0 11c0 1oo0 11c0 1oo0 11c0 1oo0 11c0 1rc0|18e5","Asia/Hebron|EET EEST IST IDT|-20 -30 -20 -30|010101010101010101010101010101012323232323232323232323232323232010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-1c2q0 5Rb0 10r0 1px0 10N0 1pz0 16p0 1jB0 16p0 1jx0 pBd0 Vz0 1oN0 11b0 1oO0 10N0 1pz0 10N0 1pb0 10N0 1pb0 10N0 1pb0 10N0 1pz0 10N0 1pb0 10N0 1pb0 11d0 1oL0 dW0 hfB0 Db0 1fB0 Rb0 bXd0 gM0 8Q00 IM0 1wM0 11z0 1C10 IL0 1s10 10n0 1o10 WL0 1zd0 On0 1ld0 11z0 1o10 14n0 1o10 14n0 1nd0 12n0 1nd0 Xz0 1q10 12n0 M10 C00 17c0 1io0 17c0 1io0 17c0 1o00 1cL0 1fB0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 17c0 1io0 18N0 1bz0 19z0 1gp0 1610 1iL0 12L0 1mN0 14o0 1lc0 Tb0 1xd1 MKX bB0 cn0 1cN0 1a00 1fA0 1cL0 1cN0 1nX0 1210 1nz0 1220 1qL0 WN0 1qL0 WN0 1qL0 11c0 1oo0 11c0 1rc0 Wo0 1rc0 Wo0 1rc0 11c0 1oo0 11c0 1oo0 11c0 1oo0 11c0 1rc0 Wo0 1rc0 11c0 1oo0 11c0 1oo0 11c0 1oo0 11c0 1oo0 11c0 1rc0 Wo0 1rc0 11c0 1oo0 11c0 1oo0 11c0 1oo0 11c0 1rc0|25e4","Asia/Ho_Chi_Minh|LMT PLMT +07 +08 +09|-76.E -76.u -70 -80 -90|0123423232|-2yC76.E bK00.a 1h7b6.u 5lz0 18o0 3Oq0 k5b0 aW00 BAM0|90e5","Asia/Hong_Kong|LMT HKT HKST HKWT JST|-7A.G -80 -90 -8u -90|0123412121212121212121212121212121212121212121212121212121212121212121|-2CFH0 1taO0 Hc0 xUu 9tBu 11z0 1tDu Rc0 1wo0 11A0 1cM0 11A0 1o00 11A0 1o00 11A0 1o00 14o0 1o00 11A0 1nX0 U10 1tz0 U10 1wn0 Rd0 1wn0 U10 1tz0 U10 1tz0 U10 1tz0 U10 1wn0 Rd0 1wn0 Rd0 1wn0 U10 1tz0 U10 1tz0 17d0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 s10 1Vz0 1cN0 1cL0 1cN0 1cL0 6fd0 14n0|73e5","Asia/Hovd|LMT +06 +07 +08|-66.A -60 -70 -80|012323232323232323232323232323232323232323232323232|-2APG6.A 2Uko6.A cKn0 1db0 1dd0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1fB0 1cL0 1cN0 1cL0 1cN0 1cL0 6hD0 11z0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 kEp0 1cJ0 1cP0 1cJ0|81e3","Asia/Irkutsk|IMT +07 +08 +09|-6V.5 -70 -80 -90|01232323232323232323232123232323232323232323232323232323232323232|-21zGV.5 pjXV.5 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 IM0 rX0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0|60e4","Europe/Istanbul|IMT EET EEST +03 +04|-1U.U -20 -30 -30 -40|0121212121212121212121212121212121212121212121234312121212121212121212121212121212121212121212121212121212121212123|-2ogNU.U dzzU.U 11b0 8tB0 1on0 1410 1db0 19B0 1in0 3Rd0 Un0 1oN0 11b0 zSN0 CL0 mp0 1Vz0 1gN0 8yn0 1yp0 ML0 1kp0 17b0 1ip0 17b0 1fB0 19X0 1ip0 19X0 1ip0 17b0 qdB0 38L0 1jd0 Tz0 l6O0 11A0 WN0 1qL0 TB0 1tX0 U10 1tz0 11B0 1in0 17d0 z90 cne0 pb0 2Cp0 1800 14o0 1dc0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1a00 1fA0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WO0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 Xc0 1qo0 WM0 1qM0 11A0 1o00 1200 1nA0 11A0 1tA0 U00 15w0|13e6","Asia/Jakarta|BMT +0720 +0730 +09 +08 WIB|-77.c -7k -7u -90 -80 -70|01232425|-1Q0Tk luM0 mPzO 8vWu 6kpu 4PXu xhcu|31e6","Asia/Jayapura|LMT +09 +0930 WIT|-9m.M -90 -9u -90|0123|-1uu9m.M sMMm.M L4nu|26e4","Asia/Jerusalem|JMT IST IDT IDDT|-2k.E -20 -30 -40|012121212121321212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-26Bek.E SyMk.E 5Rb0 10r0 1px0 10N0 1pz0 16p0 1jB0 16p0 1jx0 3LB0 Em0 or0 1cn0 1dB0 16n0 10O0 1ja0 1tC0 14o0 1cM0 1a00 11A0 1Na0 An0 1MP0 AJ0 1Kp0 LC0 1oo0 Wl0 EQN0 Db0 1fB0 Rb0 bXd0 gM0 8Q00 IM0 1wM0 11z0 1C10 IL0 1s10 10n0 1o10 WL0 1zd0 On0 1ld0 11z0 1o10 14n0 1o10 14n0 1nd0 12n0 1nd0 Xz0 1q10 12n0 1hB0 1dX0 1ep0 1aL0 1eN0 17X0 1nf0 11z0 1tB0 19W0 1e10 17b0 1ep0 1gL0 18N0 1fz0 1eN0 17b0 1gq0 1gn0 19d0 1dz0 1c10 17X0 1hB0 1gn0 19d0 1dz0 1c10 17X0 1kp0 1dz0 1c10 1aL0 1eN0 1oL0 10N0 1oL0 10N0 1oL0 10N0 1rz0 W10 1rz0 W10 1rz0 10N0 1oL0 10N0 1oL0 10N0 1rz0 W10 1rz0 W10 1rz0 10N0 1oL0 10N0 1oL0 10N0 1oL0 10N0 1rz0 W10 1rz0 W10 1rz0 10N0 1oL0 10N0 1oL0 10N0 1rz0 W10 1rz0 W10 1rz0 W10 1rz0 10N0 1oL0 10N0 1oL0|81e4","Asia/Kabul|+04 +0430|-40 -4u|01|-10Qs0|46e5","Asia/Kamchatka|LMT +11 +12 +13|-ay.A -b0 -c0 -d0|012323232323232323232321232323232323232323232323232323232323212|-1SLKy.A ivXy.A 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 IM0 rX0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 2sp0 WM0|18e4","Asia/Karachi|LMT +0530 +0630 +05 PKT PKST|-4s.c -5u -6u -50 -50 -60|012134545454|-2xoss.c 1qOKW.c 7zX0 eup0 LqMu 1fy00 1cL0 dK10 11b0 1610 1jX0|24e6","Asia/Urumqi|LMT +06|-5O.k -60|01|-1GgtO.k|32e5","Asia/Kathmandu|LMT +0530 +0545|-5F.g -5u -5J|012|-21JhF.g 2EGMb.g|12e5","Asia/Khandyga|LMT +08 +09 +10 +11|-92.d -80 -90 -a0 -b0|0123232323232323232323212323232323232323232323232343434343434343432|-21Q92.d pAp2.d 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 IM0 rX0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 qK0 yN0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 17V0 7zD0|66e2","Asia/Krasnoyarsk|LMT +06 +07 +08|-6b.q -60 -70 -80|01232323232323232323232123232323232323232323232323232323232323232|-21Hib.q prAb.q 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 IM0 rX0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0|10e5","Asia/Kuala_Lumpur|SMT +07 +0720 +0730 +09 +08|-6T.p -70 -7k -7u -90 -80|0123435|-2Bg6T.p 17anT.p l5XE 17bO 8Fyu 1so1u|71e5","Asia/Kuching|LMT +0730 +08 +0820 +09|-7l.k -7u -80 -8k -90|0123232323232323242|-1KITl.k gDbP.k 6ynu AnE 1O0k AnE 1NAk AnE 1NAk AnE 1NAk AnE 1O0k AnE 1NAk AnE pAk 8Fz0|13e4","Asia/Macau|LMT CST +09 +10 CDT|-7y.a -80 -90 -a0 -90|012323214141414141414141414141414141414141414141414141414141414141414141|-2CFHy.a 1uqKy.a PX0 1kn0 15B0 11b0 4Qq0 1oM0 11c0 1ko0 1u00 11A0 1cM0 11c0 1o00 11A0 1o00 11A0 1oo0 1400 1o00 11A0 1o00 U00 1tA0 U00 1wo0 Rc0 1wru U10 1tz0 U10 1tz0 U10 1tz0 U10 1wn0 Rd0 1wn0 Rd0 1wn0 U10 1tz0 U10 1tz0 17d0 1cK0 1cO0 1cK0 1cO0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 s10 1Vz0 1cN0 1cL0 1cN0 1cL0 6fd0 14n0|57e4","Asia/Magadan|LMT +10 +11 +12|-a3.c -a0 -b0 -c0|012323232323232323232321232323232323232323232323232323232323232312|-1Pca3.c eUo3.c 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 IM0 rX0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0 3Cq0|95e3","Asia/Makassar|LMT MMT +08 +09 WITA|-7V.A -7V.A -80 -90 -80|01234|-21JjV.A vfc0 myLV.A 8ML0|15e5","Asia/Manila|PST PDT JST|-80 -90 -90|010201010|-1kJI0 AL0 cK10 65X0 mXB0 vX0 VK10 1db0|24e6","Asia/Nicosia|LMT EET EEST|-2d.s -20 -30|01212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-1Vc2d.s 2a3cd.s 1cL0 1qp0 Xz0 19B0 19X0 1fB0 1db0 1cp0 1cL0 1fB0 19X0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1fB0 1cL0 1cN0 1cL0 1cN0 1o30 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|32e4","Asia/Novokuznetsk|LMT +06 +07 +08|-5M.M -60 -70 -80|012323232323232323232321232323232323232323232323232323232323212|-1PctM.M eULM.M 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 IM0 rX0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 2sp0 WM0|55e4","Asia/Novosibirsk|LMT +06 +07 +08|-5v.E -60 -70 -80|0123232323232323232323212323212121212121212121212121212121212121212|-21Qnv.E pAFv.E 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 IM0 rX0 1cM0 1cM0 ml0 Os0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0 4eN0|15e5","Asia/Omsk|LMT +05 +06 +07|-4R.u -50 -60 -70|01232323232323232323232123232323232323232323232323232323232323232|-224sR.u pMLR.u 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 IM0 rX0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0|12e5","Asia/Oral|LMT +03 +05 +06 +04|-3p.o -30 -50 -60 -40|01232323232323232424242424242424242424242424242|-1Pc3p.o eUop.o 23CK0 3Db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 2pB0 1cM0 1fA0 1cM0 1cM0 IM0 1EM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0|27e4","Asia/Pontianak|LMT PMT +0730 +09 +08 WITA WIB|-7h.k -7h.k -7u -90 -80 -80 -70|012324256|-2ua7h.k XE00 munL.k 8Rau 6kpu 4PXu xhcu Wqnu|23e4","Asia/Pyongyang|LMT KST JST KST|-8n -8u -90 -90|012313|-2um8n 97XR 1lTzu 2Onc0 6BA0|29e5","Asia/Qostanay|LMT +04 +05 +06|-4e.s -40 -50 -60|012323232323232323232123232323232323232323232323|-1Pc4e.s eUoe.s 23CL0 3Db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 IM0 rX0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0|","Asia/Qyzylorda|LMT +04 +05 +06|-4l.Q -40 -50 -60|01232323232323232323232323232323232323232323232|-1Pc4l.Q eUol.Q 23CL0 3Db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 3ao0 1EM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 zQl0|73e4","Asia/Rangoon|RMT +0630 +09|-6o.L -6u -90|0121|-21Jio.L SmnS.L 7j9u|48e5","Asia/Sakhalin|LMT +09 +11 +12 +10|-9u.M -90 -b0 -c0 -a0|01232323232323232323232423232323232424242424242424242424242424242|-2AGVu.M 1BoMu.M 1qFa0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 IM0 rX0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 2pB0 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0 3rd0|58e4","Asia/Samarkand|LMT +04 +05 +06|-4r.R -40 -50 -60|01232323232323232323232|-1Pc4r.R eUor.R 23CL0 3Db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0|36e4","Asia/Seoul|LMT KST JST KST KDT KDT|-8r.Q -8u -90 -90 -a0 -9u|012343434343151515151515134343|-2um8r.Q 97XV.Q 1m1zu 6CM0 Fz0 1kN0 14n0 1kN0 14L0 1zd0 On0 69B0 2I0u OL0 1FB0 Rb0 1qN0 TX0 1tB0 TX0 1tB0 TX0 1tB0 TX0 2ap0 12FBu 11A0 1o00 11A0|23e6","Asia/Srednekolymsk|LMT +10 +11 +12|-ae.Q -a0 -b0 -c0|01232323232323232323232123232323232323232323232323232323232323232|-1Pcae.Q eUoe.Q 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 IM0 rX0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0|35e2","Asia/Taipei|CST JST CDT|-80 -90 -90|01020202020202020202020202020202020202020|-1iw80 joM0 1yo0 Tz0 1ip0 1jX0 1cN0 11b0 1oN0 11b0 1oN0 11b0 1oN0 11b0 10N0 1BX0 10p0 1pz0 10p0 1pz0 10p0 1db0 1dd0 1db0 1cN0 1db0 1cN0 1db0 1cN0 1db0 1BB0 ML0 1Bd0 ML0 uq10 1db0 1cN0 1db0 97B0 AL0|74e5","Asia/Tashkent|LMT +05 +06 +07|-4B.b -50 -60 -70|012323232323232323232321|-1Pc4B.b eUnB.b 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0|23e5","Asia/Tbilisi|TBMT +03 +04 +05|-2X.b -30 -40 -50|0123232323232323232323212121232323232323232323212|-1Pc2X.b 1jUnX.b WCL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 1cK0 1cL0 1cN0 1cL0 1cN0 2pz0 1cL0 1fB0 3Nz0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 An0 Os0 WM0|11e5","Asia/Tehran|LMT TMT +0330 +04 +05 +0430|-3p.I -3p.I -3u -40 -50 -4u|01234325252525252525252525252525252525252525252525252525252525252525252525252525252525252525252525252|-2btDp.I 1d3c0 1huLT.I TXu 1pz0 sN0 vAu 1cL0 1dB0 1en0 pNB0 UL0 1cN0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0 1cN0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0 1cN0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0 1cN0 1dz0 64p0 1dz0 1cN0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0 1cN0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0 1cN0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0 1cN0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0 1cN0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0 1cN0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0 1cN0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0|14e6","Asia/Thimphu|LMT +0530 +06|-5W.A -5u -60|012|-Su5W.A 1BGMs.A|79e3","Asia/Tokyo|JST JDT|-90 -a0|010101010|-QJJ0 Rc0 1lc0 14o0 1zc0 Oo0 1zc0 Oo0|38e6","Asia/Tomsk|LMT +06 +07 +08|-5D.P -60 -70 -80|0123232323232323232323212323232323232323232323212121212121212121212|-21NhD.P pxzD.P 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 IM0 rX0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 co0 1bB0 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0 3Qp0|10e5","Asia/Ulaanbaatar|LMT +07 +08 +09|-77.w -70 -80 -90|012323232323232323232323232323232323232323232323232|-2APH7.w 2Uko7.w cKn0 1db0 1dd0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1fB0 1cL0 1cN0 1cL0 1cN0 1cL0 6hD0 11z0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 kEp0 1cJ0 1cP0 1cJ0|12e5","Asia/Ust-Nera|LMT +08 +09 +12 +11 +10|-9w.S -80 -90 -c0 -b0 -a0|012343434343434343434345434343434343434343434343434343434343434345|-21Q9w.S pApw.S 23CL0 1d90 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 IM0 rX0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 17V0 7zD0|65e2","Asia/Vladivostok|LMT +09 +10 +11|-8L.v -90 -a0 -b0|01232323232323232323232123232323232323232323232323232323232323232|-1SJIL.v itXL.v 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 IM0 rX0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0|60e4","Asia/Yakutsk|LMT +08 +09 +10|-8C.W -80 -90 -a0|01232323232323232323232123232323232323232323232323232323232323232|-21Q8C.W pAoC.W 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 IM0 rX0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0|28e4","Asia/Yekaterinburg|LMT PMT +04 +05 +06|-42.x -3J.5 -40 -50 -60|012343434343434343434343234343434343434343434343434343434343434343|-2ag42.x 7mQh.s qBvJ.5 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 IM0 rX0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0|14e5","Asia/Yerevan|LMT +03 +04 +05|-2W -30 -40 -50|0123232323232323232323212121212323232323232323232323232323232|-1Pc2W 1jUnW WCL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 2pB0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 4RX0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0|13e5","Atlantic/Azores|HMT -02 -01 +00 WET|1S.w 20 10 0 0|01212121212121212121212121212121212121212121232123212321232121212121212121212121212121212121212121232323232323232323232323232323234323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232|-2ldW0 aPX0 Sp0 LX0 1vc0 Tc0 1uM0 SM0 1vc0 Tc0 1vc0 SM0 1vc0 6600 1co0 3E00 17c0 1fA0 1a00 1io0 1a00 1io0 17c0 3I00 17c0 1cM0 1cM0 3Fc0 1cM0 1a00 1fA0 1io0 17c0 1cM0 1cM0 1a00 1fA0 1io0 1qM0 Dc0 1tA0 1cM0 1dc0 1400 gL0 IM0 s10 U00 dX0 Rc0 pd0 Rc0 gL0 Oo0 pd0 Rc0 gL0 Oo0 pd0 14o0 1cM0 1cP0 1cM0 1cM0 1cM0 1cM0 1cM0 3Co0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 qIl0 1cM0 1fA0 1cM0 1cM0 1cN0 1cL0 1cN0 1cM0 1cM0 1cM0 1cM0 1cN0 1cL0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cL0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|25e4","Atlantic/Bermuda|LMT AST ADT|4j.i 40 30|0121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-1BnRE.G 1LTbE.G 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|65e3","Atlantic/Canary|LMT -01 WET WEST|11.A 10 0 -10|01232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232|-1UtaW.o XPAW.o 1lAK0 1a10 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|54e4","Atlantic/Cape_Verde|LMT -02 -01|1y.4 20 10|01212|-2ldW0 1eEo0 7zX0 1djf0|50e4","Atlantic/Faroe|LMT WET WEST|r.4 0 -10|01212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2uSnw.U 2Wgow.U 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|49e3","Atlantic/Madeira|FMT -01 +00 +01 WET WEST|17.A 10 0 -10 0 -10|01212121212121212121212121212121212121212121232123212321232121212121212121212121212121212121212121454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454|-2ldX0 aPX0 Sp0 LX0 1vc0 Tc0 1uM0 SM0 1vc0 Tc0 1vc0 SM0 1vc0 6600 1co0 3E00 17c0 1fA0 1a00 1io0 1a00 1io0 17c0 3I00 17c0 1cM0 1cM0 3Fc0 1cM0 1a00 1fA0 1io0 17c0 1cM0 1cM0 1a00 1fA0 1io0 1qM0 Dc0 1tA0 1cM0 1dc0 1400 gL0 IM0 s10 U00 dX0 Rc0 pd0 Rc0 gL0 Oo0 pd0 Rc0 gL0 Oo0 pd0 14o0 1cM0 1cP0 1cM0 1cM0 1cM0 1cM0 1cM0 3Co0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 qIl0 1cM0 1fA0 1cM0 1cM0 1cN0 1cL0 1cN0 1cM0 1cM0 1cM0 1cM0 1cN0 1cL0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|27e4","Atlantic/Reykjavik|LMT -01 +00 GMT|1s 10 0 0|012121212121212121212121212121212121212121212121212121212121212121213|-2uWmw mfaw 1Bd0 ML0 1LB0 Cn0 1LB0 3fX0 C10 HrX0 1cO0 LB0 1EL0 LA0 1C00 Oo0 1wo0 Rc0 1wo0 Rc0 1wo0 Rc0 1zc0 Oo0 1zc0 14o0 1lc0 14o0 1lc0 14o0 1o00 11A0 1lc0 14o0 1o00 14o0 1lc0 14o0 1lc0 14o0 1lc0 14o0 1lc0 14o0 1o00 14o0 1lc0 14o0 1lc0 14o0 1lc0 14o0 1lc0 14o0 1lc0 14o0 1o00 14o0 1lc0 14o0 1lc0 14o0 1lc0 14o0 1lc0 14o0 1o00 14o0|12e4","Atlantic/South_Georgia|-02|20|0||30","Atlantic/Stanley|SMT -04 -03 -02|3P.o 40 30 20|012121212121212323212121212121212121212121212121212121212121212121212|-2kJw8.A 12bA8.A 19X0 1fB0 19X0 1ip0 19X0 1fB0 19X0 1fB0 19X0 1fB0 Cn0 1Cc10 WL0 1qL0 U10 1tz0 2mN0 WN0 1qL0 WN0 1qL0 WN0 1qL0 WN0 1tz0 U10 1tz0 WN0 1qL0 WN0 1qL0 WN0 1qL0 WN0 1qL0 WN0 1tz0 WN0 1qL0 WN0 1qL0 WN0 1qL0 WN0 1qL0 WN0 1qN0 U10 1wn0 Rd0 1wn0 U10 1tz0 U10 1tz0 U10 1tz0 U10 1tz0 U10 1wn0 U10 1tz0 U10 1tz0 U10|21e2","Australia/Sydney|AEST AEDT|-a0 -b0|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101|-293lX xcX 10jd0 yL0 1cN0 1cL0 1fB0 19X0 17c10 LA0 1C00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 14o0 1o00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 U00 1qM0 WM0 1tA0 WM0 1tA0 U00 1tA0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 11A0 1o00 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 11A0 1o00 WM0 1qM0 14o0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0|40e5","Australia/Adelaide|ACST ACDT|-9u -au|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101|-293lt xcX 10jd0 yL0 1cN0 1cL0 1fB0 19X0 17c10 LA0 1C00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 U00 1qM0 WM0 1tA0 WM0 1tA0 U00 1tA0 U00 1tA0 Oo0 1zc0 WM0 1qM0 Rc0 1zc0 U00 1tA0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 11A0 1o00 WM0 1qM0 14o0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0|11e5","Australia/Brisbane|AEST AEDT|-a0 -b0|01010101010101010|-293lX xcX 10jd0 yL0 1cN0 1cL0 1fB0 19X0 17c10 LA0 H1A0 Oo0 1zc0 Oo0 1zc0 Oo0|20e5","Australia/Broken_Hill|ACST ACDT|-9u -au|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101|-293lt xcX 10jd0 yL0 1cN0 1cL0 1fB0 19X0 17c10 LA0 1C00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 14o0 1o00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 U00 1qM0 WM0 1tA0 WM0 1tA0 U00 1tA0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 11A0 1o00 WM0 1qM0 14o0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0|18e3","Australia/Currie|AEST AEDT|-a0 -b0|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101|-29E80 19X0 10jd0 yL0 1cN0 1cL0 1fB0 19X0 17c10 LA0 1C00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 11A0 1qM0 WM0 1qM0 Oo0 1zc0 Oo0 1zc0 Oo0 1wo0 WM0 1tA0 WM0 1tA0 U00 1tA0 U00 1tA0 11A0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 11A0 1o00 1io0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1cM0 1a00 1io0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0|746","Australia/Darwin|ACST ACDT|-9u -au|010101010|-293lt xcX 10jd0 yL0 1cN0 1cL0 1fB0 19X0|12e4","Australia/Eucla|+0845 +0945|-8J -9J|0101010101010101010|-293kI xcX 10jd0 yL0 1cN0 1cL0 1gSp0 Oo0 l5A0 Oo0 iJA0 G00 zU00 IM0 1qM0 11A0 1o00 11A0|368","Australia/Hobart|AEST AEDT|-a0 -b0|010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101|-29E80 19X0 10jd0 yL0 1cN0 1cL0 1fB0 19X0 VfB0 1cM0 1o00 Rc0 1wo0 Rc0 1wo0 U00 1wo0 LA0 1C00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 11A0 1qM0 WM0 1qM0 Oo0 1zc0 Oo0 1zc0 Oo0 1wo0 WM0 1tA0 WM0 1tA0 U00 1tA0 U00 1tA0 11A0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 11A0 1o00 1io0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1cM0 1a00 1io0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0|21e4","Australia/Lord_Howe|AEST +1030 +1130 +11|-a0 -au -bu -b0|0121212121313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313|raC0 1zdu Rb0 1zd0 On0 1zd0 On0 1zd0 On0 1zd0 TXu 1qMu WLu 1tAu WLu 1tAu TXu 1tAu Onu 1zcu Onu 1zcu Onu 1zcu Rbu 1zcu Onu 1zcu Onu 1zcu 11zu 1o0u 11zu 1o0u 11zu 1o0u 11zu 1qMu WLu 11Au 1nXu 1qMu 11zu 1o0u 11zu 1o0u 11zu 1qMu WLu 1qMu 11zu 1o0u WLu 1qMu 14nu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1fAu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1fAu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1fzu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1fAu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1fAu 1cLu 1cMu 1cLu 1cMu|347","Australia/Lindeman|AEST AEDT|-a0 -b0|010101010101010101010|-293lX xcX 10jd0 yL0 1cN0 1cL0 1fB0 19X0 17c10 LA0 H1A0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0|10","Australia/Melbourne|AEST AEDT|-a0 -b0|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101|-293lX xcX 10jd0 yL0 1cN0 1cL0 1fB0 19X0 17c10 LA0 1C00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 U00 1qM0 WM0 1qM0 11A0 1tA0 U00 1tA0 U00 1tA0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 11A0 1o00 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 11A0 1o00 WM0 1qM0 14o0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0|39e5","Australia/Perth|AWST AWDT|-80 -90|0101010101010101010|-293jX xcX 10jd0 yL0 1cN0 1cL0 1gSp0 Oo0 l5A0 Oo0 iJA0 G00 zU00 IM0 1qM0 11A0 1o00 11A0|18e5","CET|CET CEST|-10 -20|01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2aFe0 11d0 1iO0 11A0 1o00 11A0 Qrc0 6i00 WM0 1fA0 1cM0 1cM0 1cM0 16M0 1gMM0 1a00 1fA0 1cM0 1cM0 1cM0 1fA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|","Pacific/Easter|EMT -07 -06 -05|7h.s 70 60 50|012121212121212121212121212123232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323|-1uSgG.w 1s4IG.w WL0 1zd0 On0 1ip0 11z0 1o10 11z0 1qN0 WL0 1ld0 14n0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 WL0 1qN0 11z0 1o10 2pA0 11z0 1o10 11z0 1qN0 WL0 1qN0 WL0 1qN0 1cL0 1cN0 11z0 1o10 11z0 1qN0 WL0 1fB0 19X0 1qN0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 17b0 1ip0 11z0 1ip0 1fz0 1fB0 11z0 1qN0 WL0 1qN0 WL0 1qN0 WL0 1qN0 11z0 1o10 11z0 1o10 11z0 1qN0 WL0 1qN0 17b0 1ip0 11z0 1o10 19X0 1fB0 1nX0 G10 1EL0 Op0 1zb0 Rd0 1wn0 Rd0 46n0 Ap0 1Nb0 Ap0 1Nb0 Ap0 1zb0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 11B0 1nX0 11B0|30e2","CST6CDT|CST CDT CWT CPT|60 50 50 50|010102301010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-261s0 1nX0 11B0 1nX0 SgN0 8x30 iw0 QwN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|","EET|EET EEST|-20 -30|010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|hDB0 1a00 1fA0 1cM0 1cM0 1cM0 1fA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|","Europe/Dublin|DMT IST GMT BST IST|p.l -y.D 0 -10 -10|01232323232324242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242|-2ax9y.D Rc0 1fzy.D 14M0 1fc0 1g00 1co0 1dc0 1co0 1oo0 1400 1dc0 19A0 1io0 1io0 WM0 1o00 14o0 1o00 17c0 1io0 17c0 1fA0 1a00 1lc0 17c0 1io0 17c0 1fA0 1a00 1io0 17c0 1io0 17c0 1fA0 1cM0 1io0 17c0 1fA0 1a00 1io0 17c0 1io0 17c0 1fA0 1a00 1io0 1qM0 Dc0 g600 14o0 1wo0 17c0 1io0 11A0 1o00 17c0 1fA0 1a00 1fA0 1cM0 1fA0 1a00 17c0 1fA0 1a00 1io0 17c0 1lc0 17c0 1fA0 1a00 1io0 17c0 1io0 17c0 1fA0 1a00 1a00 1qM0 WM0 1qM0 11A0 1o00 WM0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1tA0 IM0 90o0 U00 1tA0 U00 1tA0 U00 1tA0 U00 1tA0 WM0 1qM0 WM0 1qM0 WM0 1tA0 U00 1tA0 U00 1tA0 11z0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1o00 14o0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|12e5","EST|EST|50|0||","EST5EDT|EST EDT EWT EPT|50 40 40 40|010102301010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-261t0 1nX0 11B0 1nX0 SgN0 8x40 iv0 QwN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|","Etc/GMT-0|GMT|0|0||","Etc/GMT-1|+01|-10|0||","Pacific/Port_Moresby|+10|-a0|0||25e4","Etc/GMT-11|+11|-b0|0||","Pacific/Tarawa|+12|-c0|0||29e3","Etc/GMT-13|+13|-d0|0||","Etc/GMT-14|+14|-e0|0||","Etc/GMT-2|+02|-20|0||","Etc/GMT-3|+03|-30|0||","Etc/GMT-4|+04|-40|0||","Etc/GMT-5|+05|-50|0||","Etc/GMT-6|+06|-60|0||","Indian/Christmas|+07|-70|0||21e2","Etc/GMT-8|+08|-80|0||","Pacific/Palau|+09|-90|0||21e3","Etc/GMT+1|-01|10|0||","Etc/GMT+10|-10|a0|0||","Etc/GMT+11|-11|b0|0||","Etc/GMT+12|-12|c0|0||","Etc/GMT+3|-03|30|0||","Etc/GMT+4|-04|40|0||","Etc/GMT+5|-05|50|0||","Etc/GMT+6|-06|60|0||","Etc/GMT+7|-07|70|0||","Etc/GMT+8|-08|80|0||","Etc/GMT+9|-09|90|0||","Etc/UTC|UTC|0|0||","Europe/Amsterdam|AMT NST +0120 +0020 CEST CET|-j.w -1j.w -1k -k -20 -10|010101010101010101010101010101010101010101012323234545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545|-2aFcj.w 11b0 1iP0 11A0 1io0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1co0 1io0 1yo0 Pc0 1a00 1fA0 1Bc0 Mo0 1tc0 Uo0 1tA0 U00 1uo0 W00 1s00 VA0 1so0 Vc0 1sM0 UM0 1wo0 Rc0 1u00 Wo0 1rA0 W00 1s00 VA0 1sM0 UM0 1w00 fV0 BCX.w 1tA0 U00 1u00 Wo0 1sm0 601k WM0 1fA0 1cM0 1cM0 1cM0 16M0 1gMM0 1a00 1fA0 1cM0 1cM0 1cM0 1fA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|16e5","Europe/Andorra|WET CET CEST|0 -10 -20|012121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-UBA0 1xIN0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|79e3","Europe/Astrakhan|LMT +03 +04 +05|-3c.c -30 -40 -50|012323232323232323212121212121212121212121212121212121212121212|-1Pcrc.c eUMc.c 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 2pB0 1cM0 1fA0 1cM0 3Co0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0 3rd0|10e5","Europe/Athens|AMT EET EEST CEST CET|-1y.Q -20 -30 -20 -10|012123434121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2a61x.Q CNbx.Q mn0 kU10 9b0 3Es0 Xa0 1fb0 1dd0 k3X0 Nz0 SCp0 1vc0 SO0 1cM0 1a00 1ao0 1fc0 1a10 1fG0 1cg0 1dX0 1bX0 1cQ0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|35e5","Europe/London|GMT BST BDST|0 -10 -20|0101010101010101010101010101010101010101010101010121212121210101210101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2axa0 Rc0 1fA0 14M0 1fc0 1g00 1co0 1dc0 1co0 1oo0 1400 1dc0 19A0 1io0 1io0 WM0 1o00 14o0 1o00 17c0 1io0 17c0 1fA0 1a00 1lc0 17c0 1io0 17c0 1fA0 1a00 1io0 17c0 1io0 17c0 1fA0 1cM0 1io0 17c0 1fA0 1a00 1io0 17c0 1io0 17c0 1fA0 1a00 1io0 1qM0 Dc0 2Rz0 Dc0 1zc0 Oo0 1zc0 Rc0 1wo0 17c0 1iM0 FA0 xB0 1fA0 1a00 14o0 bb0 LA0 xB0 Rc0 1wo0 11A0 1o00 17c0 1fA0 1a00 1fA0 1cM0 1fA0 1a00 17c0 1fA0 1a00 1io0 17c0 1lc0 17c0 1fA0 1a00 1io0 17c0 1io0 17c0 1fA0 1a00 1a00 1qM0 WM0 1qM0 11A0 1o00 WM0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1tA0 IM0 90o0 U00 1tA0 U00 1tA0 U00 1tA0 U00 1tA0 WM0 1qM0 WM0 1qM0 WM0 1tA0 U00 1tA0 U00 1tA0 11z0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1o00 14o0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|10e6","Europe/Belgrade|CET CEST|-10 -20|01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-19RC0 3IP0 WM0 1fA0 1cM0 1cM0 1rc0 Qo0 1vmo0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|12e5","Europe/Berlin|CET CEST CEMT|-10 -20 -30|01010101010101210101210101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2aFe0 11d0 1iO0 11A0 1o00 11A0 Qrc0 6i00 WM0 1fA0 1cM0 1cM0 1cM0 kL0 Nc0 m10 WM0 1ao0 1cp0 dX0 jz0 Dd0 1io0 17c0 1fA0 1a00 1ehA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|41e5","Europe/Prague|CET CEST GMT|-10 -20 0|01010101010101010201010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2aFe0 11d0 1iO0 11A0 1o00 11A0 Qrc0 6i00 WM0 1fA0 1cM0 1cM0 1cM0 1cM0 1qM0 11c0 mp0 xA0 mn0 17c0 1io0 17c0 1fc0 1ao0 1bNc0 1cM0 1fA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|13e5","Europe/Brussels|WET CET CEST WEST|0 -10 -20 -10|0121212103030303030303030303030303030303030303030303212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2ehc0 3zX0 11c0 1iO0 11A0 1o00 11A0 my0 Ic0 1qM0 Rc0 1EM0 UM0 1u00 10o0 1io0 1io0 17c0 1a00 1fA0 1cM0 1cM0 1io0 17c0 1fA0 1a00 1io0 1a30 1io0 17c0 1fA0 1a00 1io0 17c0 1cM0 1cM0 1a00 1io0 1cM0 1cM0 1a00 1fA0 1io0 17c0 1cM0 1cM0 1a00 1fA0 1io0 1qM0 Dc0 y00 5Wn0 WM0 1fA0 1cM0 16M0 1iM0 16M0 1C00 Uo0 1eeo0 1a00 1fA0 1cM0 1cM0 1cM0 1fA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|21e5","Europe/Bucharest|BMT EET EEST|-1I.o -20 -30|0121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-1xApI.o 20LI.o RA0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1Axc0 On0 1fA0 1a10 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cK0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cL0 1cN0 1cL0 1fB0 1nX0 11E0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|19e5","Europe/Budapest|CET CEST|-10 -20|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2aFe0 11d0 1iO0 11A0 1ip0 17b0 1op0 1tb0 Q2m0 3Ne0 WM0 1fA0 1cM0 1cM0 1oJ0 1dc0 1030 1fA0 1cM0 1cM0 1cM0 1cM0 1fA0 1a00 1iM0 1fA0 8Ha0 Rb0 1wN0 Rb0 1BB0 Lz0 1C20 LB0 SNX0 1a10 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|17e5","Europe/Zurich|CET CEST|-10 -20|01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-19Lc0 11A0 1o00 11A0 1xG10 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|38e4","Europe/Chisinau|CMT BMT EET EEST CEST CET MSK MSD|-1T -1I.o -20 -30 -20 -10 -30 -40|012323232323232323234545467676767676767676767323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232323232|-26jdT wGMa.A 20LI.o RA0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 27A0 2en0 39g0 WM0 1fA0 1cM0 V90 1t7z0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 gL0 WO0 1cM0 1cM0 1cK0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1fB0 1nX0 11D0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|67e4","Europe/Copenhagen|CET CEST|-10 -20|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2azC0 Tz0 VuO0 60q0 WM0 1fA0 1cM0 1cM0 1cM0 S00 1HA0 Nc0 1C00 Dc0 1Nc0 Ao0 1h5A0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|12e5","Europe/Gibraltar|GMT BST BDST CET CEST|0 -10 -20 -10 -20|010101010101010101010101010101010101010101010101012121212121010121010101010101010101034343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343|-2axa0 Rc0 1fA0 14M0 1fc0 1g00 1co0 1dc0 1co0 1oo0 1400 1dc0 19A0 1io0 1io0 WM0 1o00 14o0 1o00 17c0 1io0 17c0 1fA0 1a00 1lc0 17c0 1io0 17c0 1fA0 1a00 1io0 17c0 1io0 17c0 1fA0 1cM0 1io0 17c0 1fA0 1a00 1io0 17c0 1io0 17c0 1fA0 1a00 1io0 1qM0 Dc0 2Rz0 Dc0 1zc0 Oo0 1zc0 Rc0 1wo0 17c0 1iM0 FA0 xB0 1fA0 1a00 14o0 bb0 LA0 xB0 Rc0 1wo0 11A0 1o00 17c0 1fA0 1a00 1fA0 1cM0 1fA0 1a00 17c0 1fA0 1a00 1io0 17c0 1lc0 17c0 1fA0 10Jz0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|30e3","Europe/Helsinki|HMT EET EEST|-1D.N -20 -30|0121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-1WuND.N OULD.N 1dA0 1xGq0 1cM0 1cM0 1cM0 1cN0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|12e5","Europe/Kaliningrad|CET CEST EET EEST MSK MSD +03|-10 -20 -20 -30 -30 -40 -30|01010101010101232454545454545454543232323232323232323232323232323232323232323262|-2aFe0 11d0 1iO0 11A0 1o00 11A0 Qrc0 6i00 WM0 1fA0 1cM0 1cM0 1cM0 390 7A0 1en0 12N0 1pbb0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cN0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0|44e4","Europe/Kiev|KMT EET MSK CEST CET MSD EEST|-22.4 -20 -30 -20 -10 -40 -30|0123434252525252525252525256161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161|-1Pc22.4 eUo2.4 rnz0 2Hg0 WM0 1fA0 da0 1v4m0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 Db0 3220 1cK0 1cL0 1cN0 1cL0 1cN0 1cL0 1cQ0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|34e5","Europe/Kirov|LMT +03 +04 +05|-3i.M -30 -40 -50|01232323232323232321212121212121212121212121212121212121212121|-22WM0 qH90 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 2pB0 1cM0 1fA0 1cM0 3Co0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0|48e4","Europe/Lisbon|LMT WET WEST WEMT CET CEST|A.J 0 -10 -20 -10 -20|012121212121212121212121212121212121212121212321232123212321212121212121212121212121212121212121214121212121212121212121212121212124545454212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2le00 aPX0 Sp0 LX0 1vc0 Tc0 1uM0 SM0 1vc0 Tc0 1vc0 SM0 1vc0 6600 1co0 3E00 17c0 1fA0 1a00 1io0 1a00 1io0 17c0 3I00 17c0 1cM0 1cM0 3Fc0 1cM0 1a00 1fA0 1io0 17c0 1cM0 1cM0 1a00 1fA0 1io0 1qM0 Dc0 1tA0 1cM0 1dc0 1400 gL0 IM0 s10 U00 dX0 Rc0 pd0 Rc0 gL0 Oo0 pd0 Rc0 gL0 Oo0 pd0 14o0 1cM0 1cP0 1cM0 1cM0 1cM0 1cM0 1cM0 3Co0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 pvy0 1cM0 1cM0 1fA0 1cM0 1cM0 1cN0 1cL0 1cN0 1cM0 1cM0 1cM0 1cM0 1cN0 1cL0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|27e5","Europe/Luxembourg|LMT CET CEST WET WEST WEST WET|-o.A -10 -20 0 -10 -20 -10|0121212134343434343434343434343434343434343434343434565651212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2DG0o.A t6mo.A TB0 1nX0 Up0 1o20 11A0 rW0 CM0 1qP0 R90 1EO0 UK0 1u20 10m0 1ip0 1in0 17e0 19W0 1fB0 1db0 1cp0 1in0 17d0 1fz0 1a10 1in0 1a10 1in0 17f0 1fA0 1a00 1io0 17c0 1cM0 1cM0 1a00 1io0 1cM0 1cM0 1a00 1fA0 1io0 17c0 1cM0 1cM0 1a00 1fA0 1io0 1qM0 Dc0 vA0 60L0 WM0 1fA0 1cM0 17c0 1io0 16M0 1C00 Uo0 1eeo0 1a00 1fA0 1cM0 1cM0 1cM0 1fA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|54e4","Europe/Madrid|WET WEST WEMT CET CEST|0 -10 -20 -10 -20|010101010101010101210343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343|-25Td0 19B0 1cL0 1dd0 b1z0 18p0 3HX0 17d0 1fz0 1a10 1io0 1a00 1in0 17d0 iIn0 Hd0 1cL0 bb0 1200 2s20 14n0 5aL0 Mp0 1vz0 17d0 1in0 17d0 1in0 17d0 1in0 17d0 6hX0 11B0 XHX0 1a10 1fz0 1a10 19X0 1cN0 1fz0 1a10 1fC0 1cM0 1cM0 1cM0 1fA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|62e5","Europe/Malta|CET CEST|-10 -20|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2arB0 Lz0 1cN0 1db0 1410 1on0 Wp0 1qL0 17d0 1cL0 M3B0 5M20 WM0 1fA0 1co0 17c0 1iM0 16m0 1de0 1lc0 14m0 1lc0 WO0 1qM0 GTW0 On0 1C10 LA0 1C00 LA0 1EM0 LA0 1C00 LA0 1zc0 Oo0 1C00 Oo0 1co0 1cM0 1lA0 Xc0 1qq0 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1o10 11z0 1iN0 19z0 1fB0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|42e4","Europe/Minsk|MMT EET MSK CEST CET MSD EEST +03|-1O -20 -30 -20 -10 -40 -30 -30|01234343252525252525252525261616161616161616161616161616161616161617|-1Pc1O eUnO qNX0 3gQ0 WM0 1fA0 1cM0 Al0 1tsn0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 3Fc0 1cN0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0|19e5","Europe/Monaco|PMT WET WEST WEMT CET CEST|-9.l 0 -10 -20 -10 -20|01212121212121212121212121212121212121212121212121232323232345454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454|-2nco9.l cNb9.l HA0 19A0 1iM0 11c0 1oo0 Wo0 1rc0 QM0 1EM0 UM0 1u00 10o0 1io0 1wo0 Rc0 1a00 1fA0 1cM0 1cM0 1io0 17c0 1fA0 1a00 1io0 1a00 1io0 17c0 1fA0 1a00 1io0 17c0 1cM0 1cM0 1a00 1io0 1cM0 1cM0 1a00 1fA0 1io0 17c0 1cM0 1cM0 1a00 1fA0 1io0 1qM0 Df0 2RV0 11z0 11B0 1ze0 WM0 1fA0 1cM0 1fa0 1aq0 16M0 1ekn0 1cL0 1fC0 1a00 1fA0 1cM0 1cM0 1cM0 1fA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|38e3","Europe/Moscow|MMT MMT MST MDST MSD MSK +05 EET EEST MSK|-2u.h -2v.j -3v.j -4v.j -40 -30 -50 -20 -30 -40|012132345464575454545454545454545458754545454545454545454545454545454545454595|-2ag2u.h 2pyW.W 1bA0 11X0 GN0 1Hb0 c4v.j ik0 3DA0 dz0 15A0 c10 2q10 iM10 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cN0 IM0 rX0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0|16e6","Europe/Paris|PMT WET WEST CEST CET WEMT|-9.l 0 -10 -20 -10 -20|0121212121212121212121212121212121212121212121212123434352543434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434343434|-2nco8.l cNb8.l HA0 19A0 1iM0 11c0 1oo0 Wo0 1rc0 QM0 1EM0 UM0 1u00 10o0 1io0 1wo0 Rc0 1a00 1fA0 1cM0 1cM0 1io0 17c0 1fA0 1a00 1io0 1a00 1io0 17c0 1fA0 1a00 1io0 17c0 1cM0 1cM0 1a00 1io0 1cM0 1cM0 1a00 1fA0 1io0 17c0 1cM0 1cM0 1a00 1fA0 1io0 1qM0 Df0 Ik0 5M30 WM0 1fA0 1cM0 Vx0 hB0 1aq0 16M0 1ekn0 1cL0 1fC0 1a00 1fA0 1cM0 1cM0 1cM0 1fA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|11e6","Europe/Riga|RMT LST EET MSK CEST CET MSD EEST|-1A.y -2A.y -20 -30 -20 -10 -40 -30|010102345454536363636363636363727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272727272|-25TzA.y 11A0 1iM0 ko0 gWm0 yDXA.y 2bX0 3fE0 WM0 1fA0 1cM0 1cM0 4m0 1sLy0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cN0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cN0 1o00 11A0 1o00 11A0 1qM0 3oo0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|64e4","Europe/Rome|CET CEST|-10 -20|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2arB0 Lz0 1cN0 1db0 1410 1on0 Wp0 1qL0 17d0 1cL0 M3B0 5M20 WM0 1fA0 1cM0 16M0 1iM0 16m0 1de0 1lc0 14m0 1lc0 WO0 1qM0 GTW0 On0 1C10 LA0 1C00 LA0 1EM0 LA0 1C00 LA0 1zc0 Oo0 1C00 Oo0 1C00 LA0 1zc0 Oo0 1C00 LA0 1C00 LA0 1zc0 Oo0 1C00 Oo0 1zc0 Oo0 1fC0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|39e5","Europe/Samara|LMT +03 +04 +05|-3k.k -30 -40 -50|0123232323232323232121232323232323232323232323232323232323212|-22WM0 qH90 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 2pB0 1cM0 1fA0 2y10 14m0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 2sp0 WM0|12e5","Europe/Saratov|LMT +03 +04 +05|-34.i -30 -40 -50|012323232323232321212121212121212121212121212121212121212121212|-22WM0 qH90 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 2pB0 1cM0 1cM0 1cM0 1fA0 1cM0 3Co0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0 5810|","Europe/Simferopol|SMT EET MSK CEST CET MSD EEST MSK|-2g -20 -30 -20 -10 -40 -30 -40|012343432525252525252525252161616525252616161616161616161616161616161616172|-1Pc2g eUog rEn0 2qs0 WM0 1fA0 1cM0 3V0 1u0L0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1Q00 4eL0 1cL0 1cN0 1cL0 1cN0 dX0 WL0 1cN0 1cL0 1fB0 1o30 11B0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11z0 1nW0|33e4","Europe/Sofia|EET CET CEST EEST|-20 -10 -20 -30|01212103030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030|-168L0 WM0 1fA0 1cM0 1cM0 1cN0 1mKH0 1dd0 1fb0 1ap0 1fb0 1a20 1fy0 1a30 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cK0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1fB0 1nX0 11E0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|12e5","Europe/Stockholm|CET CEST|-10 -20|01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2azC0 TB0 2yDe0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|15e5","Europe/Tallinn|TMT CET CEST EET MSK MSD EEST|-1D -10 -20 -20 -30 -40 -30|012103421212454545454545454546363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363|-26oND teD 11A0 1Ta0 4rXl KSLD 2FX0 2Jg0 WM0 1fA0 1cM0 18J0 1sTX0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cN0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o10 11A0 1qM0 5QM0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|41e4","Europe/Tirane|LMT CET CEST|-1j.k -10 -20|01212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2glBj.k 14pcj.k 5LC0 WM0 4M0 1fCK0 10n0 1op0 11z0 1pd0 11z0 1qN0 WL0 1qp0 Xb0 1qp0 Xb0 1qp0 11z0 1lB0 11z0 1qN0 11z0 1iN0 16n0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|42e4","Europe/Ulyanovsk|LMT +03 +04 +05 +02|-3d.A -30 -40 -50 -20|01232323232323232321214121212121212121212121212121212121212121212|-22WM0 qH90 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 2pB0 1cM0 1fA0 2pB0 IM0 rX0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0 3rd0|13e5","Europe/Uzhgorod|CET CEST MSK MSD EET EEST|-10 -20 -30 -40 -20 -30|010101023232323232323232320454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454|-1cqL0 6i00 WM0 1fA0 1cM0 1ml0 1Cp0 1r3W0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1Q00 1Nf0 2pw0 1cL0 1cN0 1cL0 1cN0 1cL0 1cQ0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|11e4","Europe/Vienna|CET CEST|-10 -20|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2aFe0 11d0 1iO0 11A0 1o00 11A0 3KM0 14o0 LA00 6i00 WM0 1fA0 1cM0 1cM0 1cM0 400 2qM0 1ao0 1co0 1cM0 1io0 17c0 1gHa0 19X0 1cP0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|18e5","Europe/Vilnius|WMT KMT CET EET MSK CEST MSD EEST|-1o -1z.A -10 -20 -30 -20 -40 -30|012324525254646464646464646473737373737373737352537373737373737373737373737373737373737373737373737373737373737373737373|-293do 6ILM.o 1Ooz.A zz0 Mfd0 29W0 3is0 WM0 1fA0 1cM0 LV0 1tgL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cN0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11B0 1o00 11A0 1qM0 8io0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|54e4","Europe/Volgograd|LMT +03 +04 +05|-2V.E -30 -40 -50|012323232323232321212121212121212121212121212121212121212121212|-21IqV.E psLV.E 23CL0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 2pB0 1cM0 1cM0 1cM0 1fA0 1cM0 3Co0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 8Hz0 9Jd0|10e5","Europe/Warsaw|WMT CET CEST EET EEST|-1o -10 -20 -20 -30|012121234312121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121|-2ctdo 1LXo 11d0 1iO0 11A0 1o00 11A0 1on0 11A0 6zy0 HWP0 5IM0 WM0 1fA0 1cM0 1dz0 1mL0 1en0 15B0 1aq0 1nA0 11A0 1io0 17c0 1fA0 1a00 iDX0 LA0 1cM0 1cM0 1C00 Oo0 1cM0 1cM0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1C00 LA0 uso0 1a00 1fA0 1cM0 1cM0 1cM0 1fA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cN0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|17e5","Europe/Zaporozhye|+0220 EET MSK CEST CET MSD EEST|-2k -20 -30 -20 -10 -40 -30|01234342525252525252525252526161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161|-1Pc2k eUok rdb0 2RE0 WM0 1fA0 8m0 1v9a0 1db0 1cN0 1db0 1cN0 1db0 1dd0 1cO0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cK0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cQ0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|77e4","HST|HST|a0|0||","Indian/Chagos|LMT +05 +06|-4N.E -50 -60|012|-2xosN.E 3AGLN.E|30e2","Indian/Cocos|+0630|-6u|0||596","Indian/Kerguelen|-00 +05|0 -50|01|-MG00|130","Indian/Mahe|LMT +04|-3F.M -40|01|-2yO3F.M|79e3","Indian/Maldives|MMT +05|-4S -50|01|-olgS|35e4","Indian/Mauritius|LMT +04 +05|-3O -40 -50|012121|-2xorO 34unO 14L0 12kr0 11z0|15e4","Indian/Reunion|LMT +04|-3F.Q -40|01|-2mDDF.Q|84e4","Pacific/Kwajalein|+11 +10 +09 -12 +12|-b0 -a0 -90 c0 -c0|012034|-1kln0 akp0 6Up0 12ry0 Wan0|14e3","MET|MET MEST|-10 -20|01010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-2aFe0 11d0 1iO0 11A0 1o00 11A0 Qrc0 6i00 WM0 1fA0 1cM0 1cM0 1cM0 16M0 1gMM0 1a00 1fA0 1cM0 1cM0 1cM0 1fA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|","MST|MST|70|0||","MST7MDT|MST MDT MWT MPT|70 60 60 60|010102301010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-261r0 1nX0 11B0 1nX0 SgN0 8x20 ix0 QwN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|","Pacific/Chatham|+1215 +1245 +1345|-cf -cJ -dJ|012121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212|-WqAf 1adef IM0 1C00 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1qM0 14o0 1lc0 14o0 1lc0 14o0 1lc0 17c0 1io0 17c0 1io0 17c0 1io0 17c0 1lc0 14o0 1lc0 14o0 1lc0 17c0 1io0 17c0 1io0 17c0 1lc0 14o0 1lc0 14o0 1lc0 17c0 1io0 17c0 1io0 17c0 1io0 17c0 1io0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1io0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00|600","Pacific/Apia|LMT -1130 -11 -10 +14 +13|bq.U bu b0 a0 -e0 -d0|01232345454545454545454545454545454545454545454545454545454|-2nDMx.4 1yW03.4 2rRbu 1ff0 1a00 CI0 AQ0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1io0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00|37e3","Pacific/Bougainville|+10 +09 +11|-a0 -90 -b0|0102|-16Wy0 7CN0 2MQp0|18e4","Pacific/Chuuk|+10 +09|-a0 -90|01010|-2ewy0 axB0 RVX0 axd0|49e3","Pacific/Efate|LMT +11 +12|-bd.g -b0 -c0|0121212121212121212121|-2l9nd.g 2Szcd.g 1cL0 1oN0 10L0 1fB0 19X0 1fB0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1fB0 Lz0 1Nd0 An0|66e3","Pacific/Enderbury|-12 -11 +13|c0 b0 -d0|012|nIc0 B7X0|1","Pacific/Fakaofo|-11 +13|b0 -d0|01|1Gfn0|483","Pacific/Fiji|LMT +12 +13|-bT.I -c0 -d0|0121212121212121212121212121212121212121212121212121212121212121|-2bUzT.I 3m8NT.I LA0 1EM0 IM0 nJc0 LA0 1o00 Rc0 1wo0 Ao0 1Nc0 Ao0 1Q00 xz0 1SN0 uM0 1SM0 uM0 1VA0 s00 1VA0 s00 1VA0 s00 20o0 pc0 20o0 s00 20o0 pc0 20o0 pc0 20o0 pc0 20o0 pc0 20o0 s00 1VA0 s00 20o0 pc0 20o0 pc0 20o0 pc0 20o0 pc0 20o0 s00 20o0 pc0 20o0 pc0 20o0 pc0 20o0 pc0 20o0 s00 1VA0 s00|88e4","Pacific/Galapagos|LMT -05 -06|5W.o 50 60|01212|-1yVS1.A 2dTz1.A gNd0 rz0|25e3","Pacific/Gambier|LMT -09|8X.M 90|01|-2jof0.c|125","Pacific/Guadalcanal|LMT +11|-aD.M -b0|01|-2joyD.M|11e4","Pacific/Guam|GST +09 GDT ChST|-a0 -90 -b0 -a0|01020202020202020203|-18jK0 6pB0 AhB0 3QL0 g2p0 3p91 WOX rX0 1zd0 Rb0 1wp0 Rb0 5xd0 rX0 5sN0 zb1 1C0X On0 ULb0|17e4","Pacific/Honolulu|HST HDT HWT HPT HST|au 9u 9u 9u a0|0102304|-1thLu 8x0 lef0 8wWu iAu 46p0|37e4","Pacific/Kiritimati|-1040 -10 +14|aE a0 -e0|012|nIaE B7Xk|51e2","Pacific/Kosrae|+11 +09 +10 +12|-b0 -90 -a0 -c0|01021030|-2ewz0 axC0 HBy0 akp0 axd0 WOK0 1bdz0|66e2","Pacific/Majuro|+11 +09 +10 +12|-b0 -90 -a0 -c0|0102103|-2ewz0 axC0 HBy0 akp0 6RB0 12um0|28e3","Pacific/Marquesas|LMT -0930|9i 9u|01|-2joeG|86e2","Pacific/Pago_Pago|LMT SST|bm.M b0|01|-2nDMB.c|37e2","Pacific/Nauru|LMT +1130 +09 +12|-b7.E -bu -90 -c0|01213|-1Xdn7.E QCnB.E 7mqu 1lnbu|10e3","Pacific/Niue|-1120 -1130 -11|bk bu b0|012|-KfME 17y0a|12e2","Pacific/Norfolk|+1112 +1130 +1230 +11 +12|-bc -bu -cu -b0 -c0|012134343434343434343434343434343434343434|-Kgbc W01G Oo0 1COo0 9Jcu 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0|25e4","Pacific/Noumea|LMT +11 +12|-b5.M -b0 -c0|01212121|-2l9n5.M 2EqM5.M xX0 1PB0 yn0 HeP0 Ao0|98e3","Pacific/Pitcairn|-0830 -08|8u 80|01|18Vku|56","Pacific/Pohnpei|+11 +09 +10|-b0 -90 -a0|010210|-2ewz0 axC0 HBy0 akp0 axd0|34e3","Pacific/Rarotonga|-1030 -0930 -10|au 9u a0|012121212121212121212121212|lyWu IL0 1zcu Onu 1zcu Onu 1zcu Rbu 1zcu Onu 1zcu Onu 1zcu Onu 1zcu Onu 1zcu Onu 1zcu Rbu 1zcu Onu 1zcu Onu 1zcu Onu|13e3","Pacific/Tahiti|LMT -10|9W.g a0|01|-2joe1.I|18e4","Pacific/Tongatapu|+1220 +13 +14|-ck -d0 -e0|0121212121|-1aB0k 2n5dk 15A0 1wo0 xz0 1Q10 xz0 zWN0 s00|75e3","PST8PDT|PST PDT PWT PPT|80 70 70 70|010102301010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|-261q0 1nX0 11B0 1nX0 SgN0 8x10 iy0 QwN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1cN0 1cL0 1cN0 1cL0 s10 1Vz0 LB0 1BX0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 1cN0 1fz0 1a10 1fz0 1cN0 1cL0 1cN0 1cL0 1cN0 1cL0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|","WET|WET WEST|0 -10|010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010|hDB0 1a00 1fA0 1cM0 1cM0 1cM0 1fA0 1a00 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00|"],links:["Africa/Abidjan|Africa/Bamako","Africa/Abidjan|Africa/Banjul","Africa/Abidjan|Africa/Conakry","Africa/Abidjan|Africa/Dakar","Africa/Abidjan|Africa/Freetown","Africa/Abidjan|Africa/Lome","Africa/Abidjan|Africa/Nouakchott","Africa/Abidjan|Africa/Ouagadougou","Africa/Abidjan|Africa/Timbuktu","Africa/Abidjan|Atlantic/St_Helena","Africa/Cairo|Egypt","Africa/Johannesburg|Africa/Maseru","Africa/Johannesburg|Africa/Mbabane","Africa/Lagos|Africa/Bangui","Africa/Lagos|Africa/Brazzaville","Africa/Lagos|Africa/Douala","Africa/Lagos|Africa/Kinshasa","Africa/Lagos|Africa/Libreville","Africa/Lagos|Africa/Luanda","Africa/Lagos|Africa/Malabo","Africa/Lagos|Africa/Niamey","Africa/Lagos|Africa/Porto-Novo","Africa/Maputo|Africa/Blantyre","Africa/Maputo|Africa/Bujumbura","Africa/Maputo|Africa/Gaborone","Africa/Maputo|Africa/Harare","Africa/Maputo|Africa/Kigali","Africa/Maputo|Africa/Lubumbashi","Africa/Maputo|Africa/Lusaka","Africa/Nairobi|Africa/Addis_Ababa","Africa/Nairobi|Africa/Asmara","Africa/Nairobi|Africa/Asmera","Africa/Nairobi|Africa/Dar_es_Salaam","Africa/Nairobi|Africa/Djibouti","Africa/Nairobi|Africa/Kampala","Africa/Nairobi|Africa/Mogadishu","Africa/Nairobi|Indian/Antananarivo","Africa/Nairobi|Indian/Comoro","Africa/Nairobi|Indian/Mayotte","Africa/Tripoli|Libya","America/Adak|America/Atka","America/Adak|US/Aleutian","America/Anchorage|US/Alaska","America/Argentina/Buenos_Aires|America/Buenos_Aires","America/Argentina/Catamarca|America/Argentina/ComodRivadavia","America/Argentina/Catamarca|America/Catamarca","America/Argentina/Cordoba|America/Cordoba","America/Argentina/Cordoba|America/Rosario","America/Argentina/Jujuy|America/Jujuy","America/Argentina/Mendoza|America/Mendoza","America/Atikokan|America/Coral_Harbour","America/Chicago|US/Central","America/Curacao|America/Aruba","America/Curacao|America/Kralendijk","America/Curacao|America/Lower_Princes","America/Denver|America/Shiprock","America/Denver|Navajo","America/Denver|US/Mountain","America/Detroit|US/Michigan","America/Edmonton|Canada/Mountain","America/Fort_Wayne|America/Indiana/Indianapolis","America/Fort_Wayne|America/Indianapolis","America/Fort_Wayne|US/East-Indiana","America/Halifax|Canada/Atlantic","America/Havana|Cuba","America/Indiana/Knox|America/Knox_IN","America/Indiana/Knox|US/Indiana-Starke","America/Jamaica|Jamaica","America/Kentucky/Louisville|America/Louisville","America/Los_Angeles|US/Pacific","America/Los_Angeles|US/Pacific-New","America/Manaus|Brazil/West","America/Mazatlan|Mexico/BajaSur","America/Mexico_City|Mexico/General","America/New_York|US/Eastern","America/Noronha|Brazil/DeNoronha","America/Panama|America/Cayman","America/Phoenix|US/Arizona","America/Port_of_Spain|America/Anguilla","America/Port_of_Spain|America/Antigua","America/Port_of_Spain|America/Dominica","America/Port_of_Spain|America/Grenada","America/Port_of_Spain|America/Guadeloupe","America/Port_of_Spain|America/Marigot","America/Port_of_Spain|America/Montserrat","America/Port_of_Spain|America/St_Barthelemy","America/Port_of_Spain|America/St_Kitts","America/Port_of_Spain|America/St_Lucia","America/Port_of_Spain|America/St_Thomas","America/Port_of_Spain|America/St_Vincent","America/Port_of_Spain|America/Tortola","America/Port_of_Spain|America/Virgin","America/Regina|Canada/Saskatchewan","America/Rio_Branco|America/Porto_Acre","America/Rio_Branco|Brazil/Acre","America/Santiago|Chile/Continental","America/Sao_Paulo|Brazil/East","America/St_Johns|Canada/Newfoundland","America/Tijuana|America/Ensenada","America/Tijuana|America/Santa_Isabel","America/Tijuana|Mexico/BajaNorte","America/Toronto|America/Montreal","America/Toronto|Canada/Eastern","America/Vancouver|Canada/Pacific","America/Whitehorse|Canada/Yukon","America/Winnipeg|Canada/Central","Asia/Ashgabat|Asia/Ashkhabad","Asia/Bangkok|Asia/Phnom_Penh","Asia/Bangkok|Asia/Vientiane","Asia/Dhaka|Asia/Dacca","Asia/Dubai|Asia/Muscat","Asia/Ho_Chi_Minh|Asia/Saigon","Asia/Hong_Kong|Hongkong","Asia/Jerusalem|Asia/Tel_Aviv","Asia/Jerusalem|Israel","Asia/Kathmandu|Asia/Katmandu","Asia/Kolkata|Asia/Calcutta","Asia/Kuala_Lumpur|Asia/Singapore","Asia/Kuala_Lumpur|Singapore","Asia/Macau|Asia/Macao","Asia/Makassar|Asia/Ujung_Pandang","Asia/Nicosia|Europe/Nicosia","Asia/Qatar|Asia/Bahrain","Asia/Rangoon|Asia/Yangon","Asia/Riyadh|Asia/Aden","Asia/Riyadh|Asia/Kuwait","Asia/Seoul|ROK","Asia/Shanghai|Asia/Chongqing","Asia/Shanghai|Asia/Chungking","Asia/Shanghai|Asia/Harbin","Asia/Shanghai|PRC","Asia/Taipei|ROC","Asia/Tehran|Iran","Asia/Thimphu|Asia/Thimbu","Asia/Tokyo|Japan","Asia/Ulaanbaatar|Asia/Ulan_Bator","Asia/Urumqi|Asia/Kashgar","Atlantic/Faroe|Atlantic/Faeroe","Atlantic/Reykjavik|Iceland","Atlantic/South_Georgia|Etc/GMT+2","Australia/Adelaide|Australia/South","Australia/Brisbane|Australia/Queensland","Australia/Broken_Hill|Australia/Yancowinna","Australia/Darwin|Australia/North","Australia/Hobart|Australia/Tasmania","Australia/Lord_Howe|Australia/LHI","Australia/Melbourne|Australia/Victoria","Australia/Perth|Australia/West","Australia/Sydney|Australia/ACT","Australia/Sydney|Australia/Canberra","Australia/Sydney|Australia/NSW","Etc/GMT-0|Etc/GMT","Etc/GMT-0|Etc/GMT+0","Etc/GMT-0|Etc/GMT0","Etc/GMT-0|Etc/Greenwich","Etc/GMT-0|GMT","Etc/GMT-0|GMT+0","Etc/GMT-0|GMT-0","Etc/GMT-0|GMT0","Etc/GMT-0|Greenwich","Etc/UTC|Etc/UCT","Etc/UTC|Etc/Universal","Etc/UTC|Etc/Zulu","Etc/UTC|UCT","Etc/UTC|UTC","Etc/UTC|Universal","Etc/UTC|Zulu","Europe/Belgrade|Europe/Ljubljana","Europe/Belgrade|Europe/Podgorica","Europe/Belgrade|Europe/Sarajevo","Europe/Belgrade|Europe/Skopje","Europe/Belgrade|Europe/Zagreb","Europe/Chisinau|Europe/Tiraspol","Europe/Dublin|Eire","Europe/Helsinki|Europe/Mariehamn","Europe/Istanbul|Asia/Istanbul","Europe/Istanbul|Turkey","Europe/Lisbon|Portugal","Europe/London|Europe/Belfast","Europe/London|Europe/Guernsey","Europe/London|Europe/Isle_of_Man","Europe/London|Europe/Jersey","Europe/London|GB","Europe/London|GB-Eire","Europe/Moscow|W-SU","Europe/Oslo|Arctic/Longyearbyen","Europe/Oslo|Atlantic/Jan_Mayen","Europe/Prague|Europe/Bratislava","Europe/Rome|Europe/San_Marino","Europe/Rome|Europe/Vatican","Europe/Warsaw|Poland","Europe/Zurich|Europe/Busingen","Europe/Zurich|Europe/Vaduz","Indian/Christmas|Etc/GMT-7","Pacific/Auckland|Antarctica/McMurdo","Pacific/Auckland|Antarctica/South_Pole","Pacific/Auckland|NZ","Pacific/Chatham|NZ-CHAT","Pacific/Chuuk|Pacific/Truk","Pacific/Chuuk|Pacific/Yap","Pacific/Easter|Chile/EasterIsland","Pacific/Guam|Pacific/Saipan","Pacific/Honolulu|Pacific/Johnston","Pacific/Honolulu|US/Hawaii","Pacific/Kwajalein|Kwajalein","Pacific/Pago_Pago|Pacific/Midway","Pacific/Pago_Pago|Pacific/Samoa","Pacific/Pago_Pago|US/Samoa","Pacific/Palau|Etc/GMT-9","Pacific/Pohnpei|Pacific/Ponape","Pacific/Port_Moresby|Etc/GMT-10","Pacific/Tarawa|Etc/GMT-12","Pacific/Tarawa|Pacific/Funafuti","Pacific/Tarawa|Pacific/Wake","Pacific/Tarawa|Pacific/Wallis"],countries:["AD|Europe/Andorra","AE|Asia/Dubai","AF|Asia/Kabul","AG|America/Port_of_Spain America/Antigua","AI|America/Port_of_Spain America/Anguilla","AL|Europe/Tirane","AM|Asia/Yerevan","AO|Africa/Lagos Africa/Luanda","AQ|Antarctica/Casey Antarctica/Davis Antarctica/DumontDUrville Antarctica/Mawson Antarctica/Palmer Antarctica/Rothera Antarctica/Syowa Antarctica/Troll Antarctica/Vostok Pacific/Auckland Antarctica/McMurdo","AR|America/Argentina/Buenos_Aires America/Argentina/Cordoba America/Argentina/Salta America/Argentina/Jujuy America/Argentina/Tucuman America/Argentina/Catamarca America/Argentina/La_Rioja America/Argentina/San_Juan America/Argentina/Mendoza America/Argentina/San_Luis America/Argentina/Rio_Gallegos America/Argentina/Ushuaia","AS|Pacific/Pago_Pago","AT|Europe/Vienna","AU|Australia/Lord_Howe Antarctica/Macquarie Australia/Hobart Australia/Currie Australia/Melbourne Australia/Sydney Australia/Broken_Hill Australia/Brisbane Australia/Lindeman Australia/Adelaide Australia/Darwin Australia/Perth Australia/Eucla","AW|America/Curacao America/Aruba","AX|Europe/Helsinki Europe/Mariehamn","AZ|Asia/Baku","BA|Europe/Belgrade Europe/Sarajevo","BB|America/Barbados","BD|Asia/Dhaka","BE|Europe/Brussels","BF|Africa/Abidjan Africa/Ouagadougou","BG|Europe/Sofia","BH|Asia/Qatar Asia/Bahrain","BI|Africa/Maputo Africa/Bujumbura","BJ|Africa/Lagos Africa/Porto-Novo","BL|America/Port_of_Spain America/St_Barthelemy","BM|Atlantic/Bermuda","BN|Asia/Brunei","BO|America/La_Paz","BQ|America/Curacao America/Kralendijk","BR|America/Noronha America/Belem America/Fortaleza America/Recife America/Araguaina America/Maceio America/Bahia America/Sao_Paulo America/Campo_Grande America/Cuiaba America/Santarem America/Porto_Velho America/Boa_Vista America/Manaus America/Eirunepe America/Rio_Branco","BS|America/Nassau","BT|Asia/Thimphu","BW|Africa/Maputo Africa/Gaborone","BY|Europe/Minsk","BZ|America/Belize","CA|America/St_Johns America/Halifax America/Glace_Bay America/Moncton America/Goose_Bay America/Blanc-Sablon America/Toronto America/Nipigon America/Thunder_Bay America/Iqaluit America/Pangnirtung America/Atikokan America/Winnipeg America/Rainy_River America/Resolute America/Rankin_Inlet America/Regina America/Swift_Current America/Edmonton America/Cambridge_Bay America/Yellowknife America/Inuvik America/Creston America/Dawson_Creek America/Fort_Nelson America/Vancouver America/Whitehorse America/Dawson","CC|Indian/Cocos","CD|Africa/Maputo Africa/Lagos Africa/Kinshasa Africa/Lubumbashi","CF|Africa/Lagos Africa/Bangui","CG|Africa/Lagos Africa/Brazzaville","CH|Europe/Zurich","CI|Africa/Abidjan","CK|Pacific/Rarotonga","CL|America/Santiago America/Punta_Arenas Pacific/Easter","CM|Africa/Lagos Africa/Douala","CN|Asia/Shanghai Asia/Urumqi","CO|America/Bogota","CR|America/Costa_Rica","CU|America/Havana","CV|Atlantic/Cape_Verde","CW|America/Curacao","CX|Indian/Christmas","CY|Asia/Nicosia Asia/Famagusta","CZ|Europe/Prague","DE|Europe/Zurich Europe/Berlin Europe/Busingen","DJ|Africa/Nairobi Africa/Djibouti","DK|Europe/Copenhagen","DM|America/Port_of_Spain America/Dominica","DO|America/Santo_Domingo","DZ|Africa/Algiers","EC|America/Guayaquil Pacific/Galapagos","EE|Europe/Tallinn","EG|Africa/Cairo","EH|Africa/El_Aaiun","ER|Africa/Nairobi Africa/Asmara","ES|Europe/Madrid Africa/Ceuta Atlantic/Canary","ET|Africa/Nairobi Africa/Addis_Ababa","FI|Europe/Helsinki","FJ|Pacific/Fiji","FK|Atlantic/Stanley","FM|Pacific/Chuuk Pacific/Pohnpei Pacific/Kosrae","FO|Atlantic/Faroe","FR|Europe/Paris","GA|Africa/Lagos Africa/Libreville","GB|Europe/London","GD|America/Port_of_Spain America/Grenada","GE|Asia/Tbilisi","GF|America/Cayenne","GG|Europe/London Europe/Guernsey","GH|Africa/Accra","GI|Europe/Gibraltar","GL|America/Godthab America/Danmarkshavn America/Scoresbysund America/Thule","GM|Africa/Abidjan Africa/Banjul","GN|Africa/Abidjan Africa/Conakry","GP|America/Port_of_Spain America/Guadeloupe","GQ|Africa/Lagos Africa/Malabo","GR|Europe/Athens","GS|Atlantic/South_Georgia","GT|America/Guatemala","GU|Pacific/Guam","GW|Africa/Bissau","GY|America/Guyana","HK|Asia/Hong_Kong","HN|America/Tegucigalpa","HR|Europe/Belgrade Europe/Zagreb","HT|America/Port-au-Prince","HU|Europe/Budapest","ID|Asia/Jakarta Asia/Pontianak Asia/Makassar Asia/Jayapura","IE|Europe/Dublin","IL|Asia/Jerusalem","IM|Europe/London Europe/Isle_of_Man","IN|Asia/Kolkata","IO|Indian/Chagos","IQ|Asia/Baghdad","IR|Asia/Tehran","IS|Atlantic/Reykjavik","IT|Europe/Rome","JE|Europe/London Europe/Jersey","JM|America/Jamaica","JO|Asia/Amman","JP|Asia/Tokyo","KE|Africa/Nairobi","KG|Asia/Bishkek","KH|Asia/Bangkok Asia/Phnom_Penh","KI|Pacific/Tarawa Pacific/Enderbury Pacific/Kiritimati","KM|Africa/Nairobi Indian/Comoro","KN|America/Port_of_Spain America/St_Kitts","KP|Asia/Pyongyang","KR|Asia/Seoul","KW|Asia/Riyadh Asia/Kuwait","KY|America/Panama America/Cayman","KZ|Asia/Almaty Asia/Qyzylorda Asia/Qostanay Asia/Aqtobe Asia/Aqtau Asia/Atyrau Asia/Oral","LA|Asia/Bangkok Asia/Vientiane","LB|Asia/Beirut","LC|America/Port_of_Spain America/St_Lucia","LI|Europe/Zurich Europe/Vaduz","LK|Asia/Colombo","LR|Africa/Monrovia","LS|Africa/Johannesburg Africa/Maseru","LT|Europe/Vilnius","LU|Europe/Luxembourg","LV|Europe/Riga","LY|Africa/Tripoli","MA|Africa/Casablanca","MC|Europe/Monaco","MD|Europe/Chisinau","ME|Europe/Belgrade Europe/Podgorica","MF|America/Port_of_Spain America/Marigot","MG|Africa/Nairobi Indian/Antananarivo","MH|Pacific/Majuro Pacific/Kwajalein","MK|Europe/Belgrade Europe/Skopje","ML|Africa/Abidjan Africa/Bamako","MM|Asia/Yangon","MN|Asia/Ulaanbaatar Asia/Hovd Asia/Choibalsan","MO|Asia/Macau","MP|Pacific/Guam Pacific/Saipan","MQ|America/Martinique","MR|Africa/Abidjan Africa/Nouakchott","MS|America/Port_of_Spain America/Montserrat","MT|Europe/Malta","MU|Indian/Mauritius","MV|Indian/Maldives","MW|Africa/Maputo Africa/Blantyre","MX|America/Mexico_City America/Cancun America/Merida America/Monterrey America/Matamoros America/Mazatlan America/Chihuahua America/Ojinaga America/Hermosillo America/Tijuana America/Bahia_Banderas","MY|Asia/Kuala_Lumpur Asia/Kuching","MZ|Africa/Maputo","NA|Africa/Windhoek","NC|Pacific/Noumea","NE|Africa/Lagos Africa/Niamey","NF|Pacific/Norfolk","NG|Africa/Lagos","NI|America/Managua","NL|Europe/Amsterdam","NO|Europe/Oslo","NP|Asia/Kathmandu","NR|Pacific/Nauru","NU|Pacific/Niue","NZ|Pacific/Auckland Pacific/Chatham","OM|Asia/Dubai Asia/Muscat","PA|America/Panama","PE|America/Lima","PF|Pacific/Tahiti Pacific/Marquesas Pacific/Gambier","PG|Pacific/Port_Moresby Pacific/Bougainville","PH|Asia/Manila","PK|Asia/Karachi","PL|Europe/Warsaw","PM|America/Miquelon","PN|Pacific/Pitcairn","PR|America/Puerto_Rico","PS|Asia/Gaza Asia/Hebron","PT|Europe/Lisbon Atlantic/Madeira Atlantic/Azores","PW|Pacific/Palau","PY|America/Asuncion","QA|Asia/Qatar","RE|Indian/Reunion","RO|Europe/Bucharest","RS|Europe/Belgrade","RU|Europe/Kaliningrad Europe/Moscow Europe/Simferopol Europe/Kirov Europe/Astrakhan Europe/Volgograd Europe/Saratov Europe/Ulyanovsk Europe/Samara Asia/Yekaterinburg Asia/Omsk Asia/Novosibirsk Asia/Barnaul Asia/Tomsk Asia/Novokuznetsk Asia/Krasnoyarsk Asia/Irkutsk Asia/Chita Asia/Yakutsk Asia/Khandyga Asia/Vladivostok Asia/Ust-Nera Asia/Magadan Asia/Sakhalin Asia/Srednekolymsk Asia/Kamchatka Asia/Anadyr","RW|Africa/Maputo Africa/Kigali","SA|Asia/Riyadh","SB|Pacific/Guadalcanal","SC|Indian/Mahe","SD|Africa/Khartoum","SE|Europe/Stockholm","SG|Asia/Singapore","SH|Africa/Abidjan Atlantic/St_Helena","SI|Europe/Belgrade Europe/Ljubljana","SJ|Europe/Oslo Arctic/Longyearbyen","SK|Europe/Prague Europe/Bratislava","SL|Africa/Abidjan Africa/Freetown","SM|Europe/Rome Europe/San_Marino","SN|Africa/Abidjan Africa/Dakar","SO|Africa/Nairobi Africa/Mogadishu","SR|America/Paramaribo","SS|Africa/Juba","ST|Africa/Sao_Tome","SV|America/El_Salvador","SX|America/Curacao America/Lower_Princes","SY|Asia/Damascus","SZ|Africa/Johannesburg Africa/Mbabane","TC|America/Grand_Turk","TD|Africa/Ndjamena","TF|Indian/Reunion Indian/Kerguelen","TG|Africa/Abidjan Africa/Lome","TH|Asia/Bangkok","TJ|Asia/Dushanbe","TK|Pacific/Fakaofo","TL|Asia/Dili","TM|Asia/Ashgabat","TN|Africa/Tunis","TO|Pacific/Tongatapu","TR|Europe/Istanbul","TT|America/Port_of_Spain","TV|Pacific/Funafuti","TW|Asia/Taipei","TZ|Africa/Nairobi Africa/Dar_es_Salaam","UA|Europe/Simferopol Europe/Kiev Europe/Uzhgorod Europe/Zaporozhye","UG|Africa/Nairobi Africa/Kampala","UM|Pacific/Pago_Pago Pacific/Wake Pacific/Honolulu Pacific/Midway","US|America/New_York America/Detroit America/Kentucky/Louisville America/Kentucky/Monticello America/Indiana/Indianapolis America/Indiana/Vincennes America/Indiana/Winamac America/Indiana/Marengo America/Indiana/Petersburg America/Indiana/Vevay America/Chicago America/Indiana/Tell_City America/Indiana/Knox America/Menominee America/North_Dakota/Center America/North_Dakota/New_Salem America/North_Dakota/Beulah America/Denver America/Boise America/Phoenix America/Los_Angeles America/Anchorage America/Juneau America/Sitka America/Metlakatla America/Yakutat America/Nome America/Adak Pacific/Honolulu","UY|America/Montevideo","UZ|Asia/Samarkand Asia/Tashkent","VA|Europe/Rome Europe/Vatican","VC|America/Port_of_Spain America/St_Vincent","VE|America/Caracas","VG|America/Port_of_Spain America/Tortola","VI|America/Port_of_Spain America/St_Thomas","VN|Asia/Bangkok Asia/Ho_Chi_Minh","VU|Pacific/Efate","WF|Pacific/Wallis","WS|Pacific/Apia","YE|Asia/Riyadh Asia/Aden","YT|Africa/Nairobi Indian/Mayotte","ZA|Africa/Johannesburg","ZM|Africa/Maputo Africa/Lusaka","ZW|Africa/Maputo Africa/Harare"]}),b}); \ No newline at end of file diff --git a/assets/ext/moment/moment.min.js b/assets/ext/moment/moment.min.js new file mode 100644 index 00000000..9218364c --- /dev/null +++ b/assets/ext/moment/moment.min.js @@ -0,0 +1,2 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.moment=t()}(this,function(){"use strict";var e,i;function f(){return e.apply(null,arguments)}function o(e){return e instanceof Array||"[object Array]"===Object.prototype.toString.call(e)}function u(e){return null!=e&&"[object Object]"===Object.prototype.toString.call(e)}function m(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function l(e){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(e).length;var t;for(t in e)if(m(e,t))return;return 1}function r(e){return void 0===e}function h(e){return"number"==typeof e||"[object Number]"===Object.prototype.toString.call(e)}function a(e){return e instanceof Date||"[object Date]"===Object.prototype.toString.call(e)}function d(e,t){var n,s=[];for(n=0;n>>0;for(t=0;tFe(e)?(r=e+1,o-Fe(e)):(r=e,o),{year:r,dayOfYear:a}}function Ae(e,t,n){var s,i,r=Ge(e.year(),t,n),a=Math.floor((e.dayOfYear()-r-1)/7)+1;return a<1?s=a+je(i=e.year()-1,t,n):a>je(e.year(),t,n)?(s=a-je(e.year(),t,n),i=e.year()+1):(i=e.year(),s=a),{week:s,year:i}}function je(e,t,n){var s=Ge(e,t,n),i=Ge(e+1,t,n);return(Fe(e)-s+i)/7}C("w",["ww",2],"wo","week"),C("W",["WW",2],"Wo","isoWeek"),L("week","w"),L("isoWeek","W"),A("week",5),A("isoWeek",5),ce("w",te),ce("ww",te,Q),ce("W",te),ce("WW",te,Q),ge(["w","ww","W","WW"],function(e,t,n,s){t[s.substr(0,1)]=Z(e)});function Ie(e,t){return e.slice(t,7).concat(e.slice(0,t))}C("d",0,"do","day"),C("dd",0,0,function(e){return this.localeData().weekdaysMin(this,e)}),C("ddd",0,0,function(e){return this.localeData().weekdaysShort(this,e)}),C("dddd",0,0,function(e){return this.localeData().weekdays(this,e)}),C("e",0,0,"weekday"),C("E",0,0,"isoWeekday"),L("day","d"),L("weekday","e"),L("isoWeekday","E"),A("day",11),A("weekday",11),A("isoWeekday",11),ce("d",te),ce("e",te),ce("E",te),ce("dd",function(e,t){return t.weekdaysMinRegex(e)}),ce("ddd",function(e,t){return t.weekdaysShortRegex(e)}),ce("dddd",function(e,t){return t.weekdaysRegex(e)}),ge(["dd","ddd","dddd"],function(e,t,n,s){var i=n._locale.weekdaysParse(e,s,n._strict);null!=i?t.d=i:y(n).invalidWeekday=e}),ge(["d","e","E"],function(e,t,n,s){t[s]=Z(e)});var Ze="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),ze="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),$e="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),qe=de,Be=de,Je=de;function Qe(){function e(e,t){return t.length-e.length}var t,n,s,i,r,a=[],o=[],u=[],l=[];for(t=0;t<7;t++)n=_([2e3,1]).day(t),s=me(this.weekdaysMin(n,"")),i=me(this.weekdaysShort(n,"")),r=me(this.weekdays(n,"")),a.push(s),o.push(i),u.push(r),l.push(s),l.push(i),l.push(r);a.sort(e),o.sort(e),u.sort(e),l.sort(e),this._weekdaysRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+o.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+a.join("|")+")","i")}function Xe(){return this.hours()%12||12}function Ke(e,t){C(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),t)})}function et(e,t){return t._meridiemParse}C("H",["HH",2],0,"hour"),C("h",["hh",2],0,Xe),C("k",["kk",2],0,function(){return this.hours()||24}),C("hmm",0,0,function(){return""+Xe.apply(this)+T(this.minutes(),2)}),C("hmmss",0,0,function(){return""+Xe.apply(this)+T(this.minutes(),2)+T(this.seconds(),2)}),C("Hmm",0,0,function(){return""+this.hours()+T(this.minutes(),2)}),C("Hmmss",0,0,function(){return""+this.hours()+T(this.minutes(),2)+T(this.seconds(),2)}),Ke("a",!0),Ke("A",!1),L("hour","h"),A("hour",13),ce("a",et),ce("A",et),ce("H",te),ce("h",te),ce("k",te),ce("HH",te,Q),ce("hh",te,Q),ce("kk",te,Q),ce("hmm",ne),ce("hmmss",se),ce("Hmm",ne),ce("Hmmss",se),ye(["H","HH"],Me),ye(["k","kk"],function(e,t,n){var s=Z(e);t[Me]=24===s?0:s}),ye(["a","A"],function(e,t,n){n._isPm=n._locale.isPM(e),n._meridiem=e}),ye(["h","hh"],function(e,t,n){t[Me]=Z(e),y(n).bigHour=!0}),ye("hmm",function(e,t,n){var s=e.length-2;t[Me]=Z(e.substr(0,s)),t[De]=Z(e.substr(s)),y(n).bigHour=!0}),ye("hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[Me]=Z(e.substr(0,s)),t[De]=Z(e.substr(s,2)),t[Se]=Z(e.substr(i)),y(n).bigHour=!0}),ye("Hmm",function(e,t,n){var s=e.length-2;t[Me]=Z(e.substr(0,s)),t[De]=Z(e.substr(s))}),ye("Hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[Me]=Z(e.substr(0,s)),t[De]=Z(e.substr(s,2)),t[Se]=Z(e.substr(i))});var tt=z("Hours",!0);var nt,st={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",w:"a week",ww:"%d weeks",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:Te,monthsShort:Ne,week:{dow:0,doy:6},weekdays:Ze,weekdaysMin:$e,weekdaysShort:ze,meridiemParse:/[ap]\.?m?\.?/i},it={},rt={};function at(e,t){var n,s=Math.min(e.length,t.length);for(n=0;n=t&&at(i,n)>=t-1)break;t--}r++}return nt}(e)}function ct(e){var t,n=e._a;return n&&-2===y(e).overflow&&(t=n[ve]<0||11xe(n[pe],n[ve])?ke:n[Me]<0||24je(n,r,a)?y(e)._overflowWeeks=!0:null!=u?y(e)._overflowWeekday=!0:(o=Ee(n,s,i,r,a),e._a[pe]=o.year,e._dayOfYear=o.dayOfYear)}(e),null!=e._dayOfYear&&(r=St(e._a[pe],s[pe]),(e._dayOfYear>Fe(r)||0===e._dayOfYear)&&(y(e)._overflowDayOfYear=!0),n=Ve(r,0,e._dayOfYear),e._a[ve]=n.getUTCMonth(),e._a[ke]=n.getUTCDate()),t=0;t<3&&null==e._a[t];++t)e._a[t]=a[t]=s[t];for(;t<7;t++)e._a[t]=a[t]=null==e._a[t]?2===t?1:0:e._a[t];24===e._a[Me]&&0===e._a[De]&&0===e._a[Se]&&0===e._a[Ye]&&(e._nextDay=!0,e._a[Me]=0),e._d=(e._useUTC?Ve:function(e,t,n,s,i,r,a){var o;return e<100&&0<=e?(o=new Date(e+400,t,n,s,i,r,a),isFinite(o.getFullYear())&&o.setFullYear(e)):o=new Date(e,t,n,s,i,r,a),o}).apply(null,a),i=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[Me]=24),e._w&&void 0!==e._w.d&&e._w.d!==i&&(y(e).weekdayMismatch=!0)}}function Ot(e){if(e._f!==f.ISO_8601)if(e._f!==f.RFC_2822){e._a=[],y(e).empty=!0;var t,n,s,i,r,a,o,u,l,h=""+e._i,d=h.length,c=0;for(s=H(e._f,e._locale).match(N)||[],t=0;tn.valueOf():n.valueOf()"}),pn.toJSON=function(){return this.isValid()?this.toISOString():null},pn.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},pn.unix=function(){return Math.floor(this.valueOf()/1e3)},pn.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},pn.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},pn.eraName=function(){var e,t,n,s=this.localeData().eras();for(e=0,t=s.length;ethis.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},pn.isLocal=function(){return!!this.isValid()&&!this._isUTC},pn.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},pn.isUtc=At,pn.isUTC=At,pn.zoneAbbr=function(){return this._isUTC?"UTC":""},pn.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},pn.dates=n("dates accessor is deprecated. Use date instead.",fn),pn.months=n("months accessor is deprecated. Use month instead",Ue),pn.years=n("years accessor is deprecated. Use year instead",Le),pn.zone=n("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(e,t){return null!=e?("string"!=typeof e&&(e=-e),this.utcOffset(e,t),this):-this.utcOffset()}),pn.isDSTShifted=n("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!r(this._isDSTShifted))return this._isDSTShifted;var e,t={};return v(t,this),(t=bt(t))._a?(e=(t._isUTC?_:Tt)(t._a),this._isDSTShifted=this.isValid()&&0.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--default .select2-results__option[role=group]{padding:0}.select2-container--default .select2-results__option[aria-disabled=true]{color:#999}.select2-container--default .select2-results__option[aria-selected=true]{background-color:#ddd}.select2-container--default .select2-results__option .select2-results__option{padding-left:1em}.select2-container--default .select2-results__option .select2-results__option .select2-results__group{padding-left:0}.select2-container--default .select2-results__option .select2-results__option .select2-results__option{margin-left:-1em;padding-left:2em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-2em;padding-left:3em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-3em;padding-left:4em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-4em;padding-left:5em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-5em;padding-left:6em}.select2-container--default .select2-results__option--highlighted[aria-selected]{background-color:#5897fb;color:white}.select2-container--default .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic .select2-selection--single{background-color:#f7f7f7;border:1px solid #aaa;border-radius:4px;outline:0;background-image:-webkit-linear-gradient(top, #fff 50%, #eee 100%);background-image:-o-linear-gradient(top, #fff 50%, #eee 100%);background-image:linear-gradient(to bottom, #fff 50%, #eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic .select2-selection--single:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--classic .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-right:10px}.select2-container--classic .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--classic .select2-selection--single .select2-selection__arrow{background-color:#ddd;border:none;border-left:1px solid #aaa;border-top-right-radius:4px;border-bottom-right-radius:4px;height:26px;position:absolute;top:1px;right:1px;width:20px;background-image:-webkit-linear-gradient(top, #eee 50%, #ccc 100%);background-image:-o-linear-gradient(top, #eee 50%, #ccc 100%);background-image:linear-gradient(to bottom, #eee 50%, #ccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0)}.select2-container--classic .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow{border:none;border-right:1px solid #aaa;border-radius:0;border-top-left-radius:4px;border-bottom-left-radius:4px;left:1px;right:auto}.select2-container--classic.select2-container--open .select2-selection--single{border:1px solid #5897fb}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow{background:transparent;border:none}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0;background-image:-webkit-linear-gradient(top, #fff 0%, #eee 50%);background-image:-o-linear-gradient(top, #fff 0%, #eee 50%);background-image:linear-gradient(to bottom, #fff 0%, #eee 50%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0;background-image:-webkit-linear-gradient(top, #eee 50%, #fff 100%);background-image:-o-linear-gradient(top, #eee 50%, #fff 100%);background-image:linear-gradient(to bottom, #eee 50%, #fff 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0)}.select2-container--classic .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text;outline:0}.select2-container--classic .select2-selection--multiple:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--multiple .select2-selection__rendered{list-style:none;margin:0;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__clear{display:none}.select2-container--classic .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove{color:#888;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover{color:#555}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice{float:right;margin-left:5px;margin-right:auto}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--classic.select2-container--open .select2-selection--multiple{border:1px solid #5897fb}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--classic .select2-search--dropdown .select2-search__field{border:1px solid #aaa;outline:0}.select2-container--classic .select2-search--inline .select2-search__field{outline:0;box-shadow:none}.select2-container--classic .select2-dropdown{background-color:#fff;border:1px solid transparent}.select2-container--classic .select2-dropdown--above{border-bottom:none}.select2-container--classic .select2-dropdown--below{border-top:none}.select2-container--classic .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--classic .select2-results__option[role=group]{padding:0}.select2-container--classic .select2-results__option[aria-disabled=true]{color:grey}.select2-container--classic .select2-results__option--highlighted[aria-selected]{background-color:#3875d7;color:#fff}.select2-container--classic .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic.select2-container--open .select2-dropdown{border-color:#5897fb} diff --git a/assets/ext/select2/select2.min.js b/assets/ext/select2/select2.min.js new file mode 100644 index 00000000..b073e95d --- /dev/null +++ b/assets/ext/select2/select2.min.js @@ -0,0 +1,2 @@ +/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ +!function(n){"function"==typeof define&&define.amd?define(["jquery"],n):"object"==typeof module&&module.exports?module.exports=function(e,t){return void 0===t&&(t="undefined"!=typeof window?require("jquery"):require("jquery")(e)),n(t),t}:n(jQuery)}(function(u){var e=function(){if(u&&u.fn&&u.fn.select2&&u.fn.select2.amd)var e=u.fn.select2.amd;var t,n,r,h,o,s,f,g,m,v,y,_,i,a,b;function w(e,t){return i.call(e,t)}function l(e,t){var n,r,i,o,s,a,l,c,u,d,p,h=t&&t.split("/"),f=y.map,g=f&&f["*"]||{};if(e){for(s=(e=e.split("/")).length-1,y.nodeIdCompat&&b.test(e[s])&&(e[s]=e[s].replace(b,"")),"."===e[0].charAt(0)&&h&&(e=h.slice(0,h.length-1).concat(e)),u=0;u":">",'"':""","'":"'","/":"/"};return"string"!=typeof e?e:String(e).replace(/[&<>"'\/\\]/g,function(e){return t[e]})},i.appendMany=function(e,t){if("1.7"===o.fn.jquery.substr(0,3)){var n=o();o.map(t,function(e){n=n.add(e)}),t=n}e.append(t)},i.__cache={};var n=0;return i.GetUniqueElementId=function(e){var t=e.getAttribute("data-select2-id");return null==t&&(e.id?(t=e.id,e.setAttribute("data-select2-id",t)):(e.setAttribute("data-select2-id",++n),t=n.toString())),t},i.StoreData=function(e,t,n){var r=i.GetUniqueElementId(e);i.__cache[r]||(i.__cache[r]={}),i.__cache[r][t]=n},i.GetData=function(e,t){var n=i.GetUniqueElementId(e);return t?i.__cache[n]&&null!=i.__cache[n][t]?i.__cache[n][t]:o(e).data(t):i.__cache[n]},i.RemoveData=function(e){var t=i.GetUniqueElementId(e);null!=i.__cache[t]&&delete i.__cache[t],e.removeAttribute("data-select2-id")},i}),e.define("select2/results",["jquery","./utils"],function(h,f){function r(e,t,n){this.$element=e,this.data=n,this.options=t,r.__super__.constructor.call(this)}return f.Extend(r,f.Observable),r.prototype.render=function(){var e=h('
    ');return this.options.get("multiple")&&e.attr("aria-multiselectable","true"),this.$results=e},r.prototype.clear=function(){this.$results.empty()},r.prototype.displayMessage=function(e){var t=this.options.get("escapeMarkup");this.clear(),this.hideLoading();var n=h(''),r=this.options.get("translations").get(e.message);n.append(t(r(e.args))),n[0].className+=" select2-results__message",this.$results.append(n)},r.prototype.hideMessages=function(){this.$results.find(".select2-results__message").remove()},r.prototype.append=function(e){this.hideLoading();var t=[];if(null!=e.results&&0!==e.results.length){e.results=this.sort(e.results);for(var n=0;n",{class:"select2-results__options select2-results__options--nested"});p.append(l),s.append(a),s.append(p)}else this.template(e,t);return f.StoreData(t,"data",e),t},r.prototype.bind=function(t,e){var l=this,n=t.id+"-results";this.$results.attr("id",n),t.on("results:all",function(e){l.clear(),l.append(e.data),t.isOpen()&&(l.setClasses(),l.highlightFirstItem())}),t.on("results:append",function(e){l.append(e.data),t.isOpen()&&l.setClasses()}),t.on("query",function(e){l.hideMessages(),l.showLoading(e)}),t.on("select",function(){t.isOpen()&&(l.setClasses(),l.options.get("scrollAfterSelect")&&l.highlightFirstItem())}),t.on("unselect",function(){t.isOpen()&&(l.setClasses(),l.options.get("scrollAfterSelect")&&l.highlightFirstItem())}),t.on("open",function(){l.$results.attr("aria-expanded","true"),l.$results.attr("aria-hidden","false"),l.setClasses(),l.ensureHighlightVisible()}),t.on("close",function(){l.$results.attr("aria-expanded","false"),l.$results.attr("aria-hidden","true"),l.$results.removeAttr("aria-activedescendant")}),t.on("results:toggle",function(){var e=l.getHighlightedResults();0!==e.length&&e.trigger("mouseup")}),t.on("results:select",function(){var e=l.getHighlightedResults();if(0!==e.length){var t=f.GetData(e[0],"data");"true"==e.attr("aria-selected")?l.trigger("close",{}):l.trigger("select",{data:t})}}),t.on("results:previous",function(){var e=l.getHighlightedResults(),t=l.$results.find("[aria-selected]"),n=t.index(e);if(!(n<=0)){var r=n-1;0===e.length&&(r=0);var i=t.eq(r);i.trigger("mouseenter");var o=l.$results.offset().top,s=i.offset().top,a=l.$results.scrollTop()+(s-o);0===r?l.$results.scrollTop(0):s-o<0&&l.$results.scrollTop(a)}}),t.on("results:next",function(){var e=l.getHighlightedResults(),t=l.$results.find("[aria-selected]"),n=t.index(e)+1;if(!(n>=t.length)){var r=t.eq(n);r.trigger("mouseenter");var i=l.$results.offset().top+l.$results.outerHeight(!1),o=r.offset().top+r.outerHeight(!1),s=l.$results.scrollTop()+o-i;0===n?l.$results.scrollTop(0):ithis.$results.outerHeight()||o<0)&&this.$results.scrollTop(i)}},r.prototype.template=function(e,t){var n=this.options.get("templateResult"),r=this.options.get("escapeMarkup"),i=n(e,t);null==i?t.style.display="none":"string"==typeof i?t.innerHTML=r(i):h(t).append(i)},r}),e.define("select2/keys",[],function(){return{BACKSPACE:8,TAB:9,ENTER:13,SHIFT:16,CTRL:17,ALT:18,ESC:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,DELETE:46}}),e.define("select2/selection/base",["jquery","../utils","../keys"],function(n,r,i){function o(e,t){this.$element=e,this.options=t,o.__super__.constructor.call(this)}return r.Extend(o,r.Observable),o.prototype.render=function(){var e=n('');return this._tabindex=0,null!=r.GetData(this.$element[0],"old-tabindex")?this._tabindex=r.GetData(this.$element[0],"old-tabindex"):null!=this.$element.attr("tabindex")&&(this._tabindex=this.$element.attr("tabindex")),e.attr("title",this.$element.attr("title")),e.attr("tabindex",this._tabindex),e.attr("aria-disabled","false"),this.$selection=e},o.prototype.bind=function(e,t){var n=this,r=e.id+"-results";this.container=e,this.$selection.on("focus",function(e){n.trigger("focus",e)}),this.$selection.on("blur",function(e){n._handleBlur(e)}),this.$selection.on("keydown",function(e){n.trigger("keypress",e),e.which===i.SPACE&&e.preventDefault()}),e.on("results:focus",function(e){n.$selection.attr("aria-activedescendant",e.data._resultId)}),e.on("selection:update",function(e){n.update(e.data)}),e.on("open",function(){n.$selection.attr("aria-expanded","true"),n.$selection.attr("aria-owns",r),n._attachCloseHandler(e)}),e.on("close",function(){n.$selection.attr("aria-expanded","false"),n.$selection.removeAttr("aria-activedescendant"),n.$selection.removeAttr("aria-owns"),n.$selection.trigger("focus"),n._detachCloseHandler(e)}),e.on("enable",function(){n.$selection.attr("tabindex",n._tabindex),n.$selection.attr("aria-disabled","false")}),e.on("disable",function(){n.$selection.attr("tabindex","-1"),n.$selection.attr("aria-disabled","true")})},o.prototype._handleBlur=function(e){var t=this;window.setTimeout(function(){document.activeElement==t.$selection[0]||n.contains(t.$selection[0],document.activeElement)||t.trigger("blur",e)},1)},o.prototype._attachCloseHandler=function(e){n(document.body).on("mousedown.select2."+e.id,function(e){var t=n(e.target).closest(".select2");n(".select2.select2-container--open").each(function(){this!=t[0]&&r.GetData(this,"element").select2("close")})})},o.prototype._detachCloseHandler=function(e){n(document.body).off("mousedown.select2."+e.id)},o.prototype.position=function(e,t){t.find(".selection").append(e)},o.prototype.destroy=function(){this._detachCloseHandler(this.container)},o.prototype.update=function(e){throw new Error("The `update` method must be defined in child classes.")},o.prototype.isEnabled=function(){return!this.isDisabled()},o.prototype.isDisabled=function(){return this.options.get("disabled")},o}),e.define("select2/selection/single",["jquery","./base","../utils","../keys"],function(e,t,n,r){function i(){i.__super__.constructor.apply(this,arguments)}return n.Extend(i,t),i.prototype.render=function(){var e=i.__super__.render.call(this);return e.addClass("select2-selection--single"),e.html(''),e},i.prototype.bind=function(t,e){var n=this;i.__super__.bind.apply(this,arguments);var r=t.id+"-container";this.$selection.find(".select2-selection__rendered").attr("id",r).attr("role","textbox").attr("aria-readonly","true"),this.$selection.attr("aria-labelledby",r),this.$selection.on("mousedown",function(e){1===e.which&&n.trigger("toggle",{originalEvent:e})}),this.$selection.on("focus",function(e){}),this.$selection.on("blur",function(e){}),t.on("focus",function(e){t.isOpen()||n.$selection.trigger("focus")})},i.prototype.clear=function(){var e=this.$selection.find(".select2-selection__rendered");e.empty(),e.removeAttr("title")},i.prototype.display=function(e,t){var n=this.options.get("templateSelection");return this.options.get("escapeMarkup")(n(e,t))},i.prototype.selectionContainer=function(){return e("")},i.prototype.update=function(e){if(0!==e.length){var t=e[0],n=this.$selection.find(".select2-selection__rendered"),r=this.display(t,n);n.empty().append(r);var i=t.title||t.text;i?n.attr("title",i):n.removeAttr("title")}else this.clear()},i}),e.define("select2/selection/multiple",["jquery","./base","../utils"],function(i,e,l){function n(e,t){n.__super__.constructor.apply(this,arguments)}return l.Extend(n,e),n.prototype.render=function(){var e=n.__super__.render.call(this);return e.addClass("select2-selection--multiple"),e.html('
      '),e},n.prototype.bind=function(e,t){var r=this;n.__super__.bind.apply(this,arguments),this.$selection.on("click",function(e){r.trigger("toggle",{originalEvent:e})}),this.$selection.on("click",".select2-selection__choice__remove",function(e){if(!r.isDisabled()){var t=i(this).parent(),n=l.GetData(t[0],"data");r.trigger("unselect",{originalEvent:e,data:n})}})},n.prototype.clear=function(){var e=this.$selection.find(".select2-selection__rendered");e.empty(),e.removeAttr("title")},n.prototype.display=function(e,t){var n=this.options.get("templateSelection");return this.options.get("escapeMarkup")(n(e,t))},n.prototype.selectionContainer=function(){return i('
    • ×
    • ')},n.prototype.update=function(e){if(this.clear(),0!==e.length){for(var t=[],n=0;n×');a.StoreData(r[0],"data",t),this.$selection.find(".select2-selection__rendered").prepend(r)}},e}),e.define("select2/selection/search",["jquery","../utils","../keys"],function(r,a,l){function e(e,t,n){e.call(this,t,n)}return e.prototype.render=function(e){var t=r('');this.$searchContainer=t,this.$search=t.find("input");var n=e.call(this);return this._transferTabIndex(),n},e.prototype.bind=function(e,t,n){var r=this,i=t.id+"-results";e.call(this,t,n),t.on("open",function(){r.$search.attr("aria-controls",i),r.$search.trigger("focus")}),t.on("close",function(){r.$search.val(""),r.$search.removeAttr("aria-controls"),r.$search.removeAttr("aria-activedescendant"),r.$search.trigger("focus")}),t.on("enable",function(){r.$search.prop("disabled",!1),r._transferTabIndex()}),t.on("disable",function(){r.$search.prop("disabled",!0)}),t.on("focus",function(e){r.$search.trigger("focus")}),t.on("results:focus",function(e){e.data._resultId?r.$search.attr("aria-activedescendant",e.data._resultId):r.$search.removeAttr("aria-activedescendant")}),this.$selection.on("focusin",".select2-search--inline",function(e){r.trigger("focus",e)}),this.$selection.on("focusout",".select2-search--inline",function(e){r._handleBlur(e)}),this.$selection.on("keydown",".select2-search--inline",function(e){if(e.stopPropagation(),r.trigger("keypress",e),r._keyUpPrevented=e.isDefaultPrevented(),e.which===l.BACKSPACE&&""===r.$search.val()){var t=r.$searchContainer.prev(".select2-selection__choice");if(0this.maximumInputLength?this.trigger("results:message",{message:"inputTooLong",args:{maximum:this.maximumInputLength,input:t.term,params:t}}):e.call(this,t,n)},e}),e.define("select2/data/maximumSelectionLength",[],function(){function e(e,t,n){this.maximumSelectionLength=n.get("maximumSelectionLength"),e.call(this,t,n)}return e.prototype.bind=function(e,t,n){var r=this;e.call(this,t,n),t.on("select",function(){r._checkIfMaximumSelected()})},e.prototype.query=function(e,t,n){var r=this;this._checkIfMaximumSelected(function(){e.call(r,t,n)})},e.prototype._checkIfMaximumSelected=function(e,n){var r=this;this.current(function(e){var t=null!=e?e.length:0;0=r.maximumSelectionLength?r.trigger("results:message",{message:"maximumSelected",args:{maximum:r.maximumSelectionLength}}):n&&n()})},e}),e.define("select2/dropdown",["jquery","./utils"],function(t,e){function n(e,t){this.$element=e,this.options=t,n.__super__.constructor.call(this)}return e.Extend(n,e.Observable),n.prototype.render=function(){var e=t('');return e.attr("dir",this.options.get("dir")),this.$dropdown=e},n.prototype.bind=function(){},n.prototype.position=function(e,t){},n.prototype.destroy=function(){this.$dropdown.remove()},n}),e.define("select2/dropdown/search",["jquery","../utils"],function(o,e){function t(){}return t.prototype.render=function(e){var t=e.call(this),n=o('');return this.$searchContainer=n,this.$search=n.find("input"),t.prepend(n),t},t.prototype.bind=function(e,t,n){var r=this,i=t.id+"-results";e.call(this,t,n),this.$search.on("keydown",function(e){r.trigger("keypress",e),r._keyUpPrevented=e.isDefaultPrevented()}),this.$search.on("input",function(e){o(this).off("keyup")}),this.$search.on("keyup input",function(e){r.handleSearch(e)}),t.on("open",function(){r.$search.attr("tabindex",0),r.$search.attr("aria-controls",i),r.$search.trigger("focus"),window.setTimeout(function(){r.$search.trigger("focus")},0)}),t.on("close",function(){r.$search.attr("tabindex",-1),r.$search.removeAttr("aria-controls"),r.$search.removeAttr("aria-activedescendant"),r.$search.val(""),r.$search.trigger("blur")}),t.on("focus",function(){t.isOpen()||r.$search.trigger("focus")}),t.on("results:all",function(e){null!=e.query.term&&""!==e.query.term||(r.showSearch(e)?r.$searchContainer.removeClass("select2-search--hide"):r.$searchContainer.addClass("select2-search--hide"))}),t.on("results:focus",function(e){e.data._resultId?r.$search.attr("aria-activedescendant",e.data._resultId):r.$search.removeAttr("aria-activedescendant")})},t.prototype.handleSearch=function(e){if(!this._keyUpPrevented){var t=this.$search.val();this.trigger("query",{term:t})}this._keyUpPrevented=!1},t.prototype.showSearch=function(e,t){return!0},t}),e.define("select2/dropdown/hidePlaceholder",[],function(){function e(e,t,n,r){this.placeholder=this.normalizePlaceholder(n.get("placeholder")),e.call(this,t,n,r)}return e.prototype.append=function(e,t){t.results=this.removePlaceholder(t.results),e.call(this,t)},e.prototype.normalizePlaceholder=function(e,t){return"string"==typeof t&&(t={id:"",text:t}),t},e.prototype.removePlaceholder=function(e,t){for(var n=t.slice(0),r=t.length-1;0<=r;r--){var i=t[r];this.placeholder.id===i.id&&n.splice(r,1)}return n},e}),e.define("select2/dropdown/infiniteScroll",["jquery"],function(n){function e(e,t,n,r){this.lastParams={},e.call(this,t,n,r),this.$loadingMore=this.createLoadingMore(),this.loading=!1}return e.prototype.append=function(e,t){this.$loadingMore.remove(),this.loading=!1,e.call(this,t),this.showLoadingMore(t)&&(this.$results.append(this.$loadingMore),this.loadMoreIfNeeded())},e.prototype.bind=function(e,t,n){var r=this;e.call(this,t,n),t.on("query",function(e){r.lastParams=e,r.loading=!0}),t.on("query:append",function(e){r.lastParams=e,r.loading=!0}),this.$results.on("scroll",this.loadMoreIfNeeded.bind(this))},e.prototype.loadMoreIfNeeded=function(){var e=n.contains(document.documentElement,this.$loadingMore[0]);if(!this.loading&&e){var t=this.$results.offset().top+this.$results.outerHeight(!1);this.$loadingMore.offset().top+this.$loadingMore.outerHeight(!1)<=t+50&&this.loadMore()}},e.prototype.loadMore=function(){this.loading=!0;var e=n.extend({},{page:1},this.lastParams);e.page++,this.trigger("query:append",e)},e.prototype.showLoadingMore=function(e,t){return t.pagination&&t.pagination.more},e.prototype.createLoadingMore=function(){var e=n('
    • '),t=this.options.get("translations").get("loadingMore");return e.html(t(this.lastParams)),e},e}),e.define("select2/dropdown/attachBody",["jquery","../utils"],function(f,a){function e(e,t,n){this.$dropdownParent=f(n.get("dropdownParent")||document.body),e.call(this,t,n)}return e.prototype.bind=function(e,t,n){var r=this;e.call(this,t,n),t.on("open",function(){r._showDropdown(),r._attachPositioningHandler(t),r._bindContainerResultHandlers(t)}),t.on("close",function(){r._hideDropdown(),r._detachPositioningHandler(t)}),this.$dropdownContainer.on("mousedown",function(e){e.stopPropagation()})},e.prototype.destroy=function(e){e.call(this),this.$dropdownContainer.remove()},e.prototype.position=function(e,t,n){t.attr("class",n.attr("class")),t.removeClass("select2"),t.addClass("select2-container--open"),t.css({position:"absolute",top:-999999}),this.$container=n},e.prototype.render=function(e){var t=f(""),n=e.call(this);return t.append(n),this.$dropdownContainer=t},e.prototype._hideDropdown=function(e){this.$dropdownContainer.detach()},e.prototype._bindContainerResultHandlers=function(e,t){if(!this._containerResultsHandlersBound){var n=this;t.on("results:all",function(){n._positionDropdown(),n._resizeDropdown()}),t.on("results:append",function(){n._positionDropdown(),n._resizeDropdown()}),t.on("results:message",function(){n._positionDropdown(),n._resizeDropdown()}),t.on("select",function(){n._positionDropdown(),n._resizeDropdown()}),t.on("unselect",function(){n._positionDropdown(),n._resizeDropdown()}),this._containerResultsHandlersBound=!0}},e.prototype._attachPositioningHandler=function(e,t){var n=this,r="scroll.select2."+t.id,i="resize.select2."+t.id,o="orientationchange.select2."+t.id,s=this.$container.parents().filter(a.hasScroll);s.each(function(){a.StoreData(this,"select2-scroll-position",{x:f(this).scrollLeft(),y:f(this).scrollTop()})}),s.on(r,function(e){var t=a.GetData(this,"select2-scroll-position");f(this).scrollTop(t.y)}),f(window).on(r+" "+i+" "+o,function(e){n._positionDropdown(),n._resizeDropdown()})},e.prototype._detachPositioningHandler=function(e,t){var n="scroll.select2."+t.id,r="resize.select2."+t.id,i="orientationchange.select2."+t.id;this.$container.parents().filter(a.hasScroll).off(n),f(window).off(n+" "+r+" "+i)},e.prototype._positionDropdown=function(){var e=f(window),t=this.$dropdown.hasClass("select2-dropdown--above"),n=this.$dropdown.hasClass("select2-dropdown--below"),r=null,i=this.$container.offset();i.bottom=i.top+this.$container.outerHeight(!1);var o={height:this.$container.outerHeight(!1)};o.top=i.top,o.bottom=i.top+o.height;var s=this.$dropdown.outerHeight(!1),a=e.scrollTop(),l=e.scrollTop()+e.height(),c=ai.bottom+s,d={left:i.left,top:o.bottom},p=this.$dropdownParent;"static"===p.css("position")&&(p=p.offsetParent());var h={top:0,left:0};(f.contains(document.body,p[0])||p[0].isConnected)&&(h=p.offset()),d.top-=h.top,d.left-=h.left,t||n||(r="below"),u||!c||t?!c&&u&&t&&(r="below"):r="above",("above"==r||t&&"below"!==r)&&(d.top=o.top-h.top-s),null!=r&&(this.$dropdown.removeClass("select2-dropdown--below select2-dropdown--above").addClass("select2-dropdown--"+r),this.$container.removeClass("select2-container--below select2-container--above").addClass("select2-container--"+r)),this.$dropdownContainer.css(d)},e.prototype._resizeDropdown=function(){var e={width:this.$container.outerWidth(!1)+"px"};this.options.get("dropdownAutoWidth")&&(e.minWidth=e.width,e.position="relative",e.width="auto"),this.$dropdown.css(e)},e.prototype._showDropdown=function(e){this.$dropdownContainer.appendTo(this.$dropdownParent),this._positionDropdown(),this._resizeDropdown()},e}),e.define("select2/dropdown/minimumResultsForSearch",[],function(){function e(e,t,n,r){this.minimumResultsForSearch=n.get("minimumResultsForSearch"),this.minimumResultsForSearch<0&&(this.minimumResultsForSearch=1/0),e.call(this,t,n,r)}return e.prototype.showSearch=function(e,t){return!(function e(t){for(var n=0,r=0;r');return e.attr("dir",this.options.get("dir")),this.$container=e,this.$container.addClass("select2-container--"+this.options.get("theme")),u.StoreData(e[0],"element",this.$element),e},d}),e.define("jquery-mousewheel",["jquery"],function(e){return e}),e.define("jquery.select2",["jquery","jquery-mousewheel","./select2/core","./select2/defaults","./select2/utils"],function(i,e,o,t,s){if(null==i.fn.select2){var a=["open","close","destroy"];i.fn.select2=function(t){if("object"==typeof(t=t||{}))return this.each(function(){var e=i.extend(!0,{},t);new o(i(this),e)}),this;if("string"!=typeof t)throw new Error("Invalid arguments for Select2: "+t);var n,r=Array.prototype.slice.call(arguments,1);return this.each(function(){var e=s.GetData(this,"select2");null==e&&window.console&&console.error&&console.error("The select2('"+t+"') method was called on an element that is not using Select2."),n=e[t].apply(e,r)}),-1]*)?>', 'gi'), ''); + }); + trumbowyg.$ed.html(processNodes); + }, 0); + }); + } + } + } + }); +})(jQuery); diff --git a/assets/ext/trumbowyg/plugins/allowtagsfrompaste/trumbowyg.allowtagsfrompaste.min.js b/assets/ext/trumbowyg/plugins/allowtagsfrompaste/trumbowyg.allowtagsfrompaste.min.js new file mode 100644 index 00000000..4d28b00e --- /dev/null +++ b/assets/ext/trumbowyg/plugins/allowtagsfrompaste/trumbowyg.allowtagsfrompaste.min.js @@ -0,0 +1 @@ +!function(e){"use strict";var a={allowedTags:[],removableTags:["a","abbr","address","b","bdi","bdo","blockquote","br","cite","code","del","dfn","details","em","h1","h2","h3","h4","h5","h6","hr","i","ins","kbd","mark","meter","pre","progress","q","rp","rt","ruby","s","samp","small","span","strong","sub","summary","sup","time","u","var","wbr","img","map","area","canvas","figcaption","figure","picture","audio","source","track","video","ul","ol","li","dl","dt","dd","table","caption","th","tr","td","thead","tbody","tfoot","col","colgroup","style","div","p","form","input","textarea","button","select","optgroup","option","label","fieldset","legend","datalist","keygen","output","iframe","link","nav","header","hgroup","footer","main","section","article","aside","dialog","script","noscript","embed","object","param"]};e.extend(!0,e.trumbowyg,{plugins:{allowTagsFromPaste:{init:function(t){if(t.o.removeformatPasted=!1,t.o.plugins.allowTagsFromPaste){var o=t.o.plugins.allowTagsFromPaste.allowedTags||a.allowedTags,r=t.o.plugins.allowTagsFromPaste.removableTags||a.removableTags;if(0!==o.length){var s=e(r).not(o).get();t.pasteHandlers.push(function(){setTimeout(function(){var a=t.$ed.html();e.each(s,function(e,t){a=a.replace(new RegExp("<\\/?"+t+"(\\s[^>]*)?>","gi"),"")}),t.$ed.html(a)},0)})}}}}}})}(jQuery); \ No newline at end of file diff --git a/assets/ext/trumbowyg/plugins/base64/trumbowyg.base64.js b/assets/ext/trumbowyg/plugins/base64/trumbowyg.base64.js new file mode 100644 index 00000000..41f9f2e1 --- /dev/null +++ b/assets/ext/trumbowyg/plugins/base64/trumbowyg.base64.js @@ -0,0 +1,153 @@ +/* =========================================================== + * trumbowyg.base64.js v1.0 + * Base64 plugin for Trumbowyg + * http://alex-d.github.com/Trumbowyg + * =========================================================== + * Author : Cyril Biencourt (lizardK) + */ + +(function ($) { + 'use strict'; + + var isSupported = function () { + return typeof FileReader !== 'undefined'; + }; + + var isValidImage = function (type) { + return /^data:image\/[a-z]?/i.test(type); + }; + + $.extend(true, $.trumbowyg, { + langs: { + // jshint camelcase:false + en: { + base64: 'Image as base64', + file: 'File', + errFileReaderNotSupported: 'FileReader is not supported by your browser.', + errInvalidImage: 'Invalid image file.' + }, + da: { + base64: 'Billede som base64', + file: 'Fil', + errFileReaderNotSupported: 'FileReader er ikke understøttet af din browser.', + errInvalidImage: 'Ugyldig billedfil.' + }, + fr: { + base64: 'Image en base64', + file: 'Fichier' + }, + cs: { + base64: 'Vložit obrázek', + file: 'Soubor' + }, + zh_cn: { + base64: '图片(Base64编码)', + file: '文件' + }, + nl: { + base64: 'Afbeelding inline', + file: 'Bestand', + errFileReaderNotSupported: 'Uw browser ondersteunt deze functionaliteit niet.', + errInvalidImage: 'De gekozen afbeelding is ongeldig.' + }, + ru: { + base64: 'Изображение как код в base64', + file: 'Файл', + errFileReaderNotSupported: 'FileReader не поддерживается вашим браузером.', + errInvalidImage: 'Недопустимый файл изображения.' + }, + ja: { + base64: '画像 (Base64形式)', + file: 'ファイル', + errFileReaderNotSupported: 'あなたのブラウザーはFileReaderをサポートしていません', + errInvalidImage: '画像形式が正しくありません' + }, + tr: { + base64: 'Base64 olarak resim', + file: 'Dosya', + errFileReaderNotSupported: 'FileReader tarayıcınız tarafından desteklenmiyor.', + errInvalidImage: 'Geçersiz resim dosyası.' + }, + zh_tw: { + base64: '圖片(base64編碼)', + file: '檔案', + errFileReaderNotSupported: '你的瀏覽器不支援FileReader', + errInvalidImage: '不正確的檔案格式' + }, + pt_br: { + base64: 'Imagem em base64', + file: 'Arquivo', + errFileReaderNotSupported: 'FileReader não é suportado pelo seu navegador.', + errInvalidImage: 'Arquivo de imagem inválido.' + }, + ko: { + base64: '그림 넣기(base64)', + file: '파일', + errFileReaderNotSupported: 'FileReader가 현재 브라우저를 지원하지 않습니다.', + errInvalidImage: '유효하지 않은 파일' + }, + }, + // jshint camelcase:true + + plugins: { + base64: { + shouldInit: isSupported, + init: function (trumbowyg) { + var btnDef = { + isSupported: isSupported, + fn: function () { + trumbowyg.saveRange(); + + var file; + var $modal = trumbowyg.openModalInsert( + // Title + trumbowyg.lang.base64, + + // Fields + { + file: { + type: 'file', + required: true, + attributes: { + accept: 'image/*' + } + }, + alt: { + label: 'description', + value: trumbowyg.getRangeText() + } + }, + + // Callback + function (values) { + var fReader = new FileReader(); + + fReader.onloadend = function (e) { + if (isValidImage(e.target.result)) { + trumbowyg.execCmd('insertImage', fReader.result, false, true); + $(['img[src="', fReader.result, '"]:not([alt])'].join(''), trumbowyg.$box).attr('alt', values.alt); + trumbowyg.closeModal(); + } else { + trumbowyg.addErrorOnModalField( + $('input[type=file]', $modal), + trumbowyg.lang.errInvalidImage + ); + } + }; + + fReader.readAsDataURL(file); + } + ); + + $('input[type=file]').on('change', function (e) { + file = e.target.files[0]; + }); + } + }; + + trumbowyg.addBtnDef('base64', btnDef); + } + } + } + }); +})(jQuery); diff --git a/assets/ext/trumbowyg/plugins/base64/trumbowyg.base64.min.js b/assets/ext/trumbowyg/plugins/base64/trumbowyg.base64.min.js new file mode 100644 index 00000000..a954cfe5 --- /dev/null +++ b/assets/ext/trumbowyg/plugins/base64/trumbowyg.base64.min.js @@ -0,0 +1 @@ +!function(e){"use strict";var a=function(){return"undefined"!=typeof FileReader},r=function(e){return/^data:image\/[a-z]?/i.test(e)};e.extend(!0,e.trumbowyg,{langs:{en:{base64:"Image as base64",file:"File",errFileReaderNotSupported:"FileReader is not supported by your browser.",errInvalidImage:"Invalid image file."},da:{base64:"Billede som base64",file:"Fil",errFileReaderNotSupported:"FileReader er ikke understøttet af din browser.",errInvalidImage:"Ugyldig billedfil."},fr:{base64:"Image en base64",file:"Fichier"},cs:{base64:"Vložit obrázek",file:"Soubor"},zh_cn:{base64:"图片(Base64编码)",file:"文件"},nl:{base64:"Afbeelding inline",file:"Bestand",errFileReaderNotSupported:"Uw browser ondersteunt deze functionaliteit niet.",errInvalidImage:"De gekozen afbeelding is ongeldig."},ru:{base64:"Изображение как код в base64",file:"Файл",errFileReaderNotSupported:"FileReader не поддерживается вашим браузером.",errInvalidImage:"Недопустимый файл изображения."},ja:{base64:"画像 (Base64形式)",file:"ファイル",errFileReaderNotSupported:"あなたのブラウザーはFileReaderをサポートしていません",errInvalidImage:"画像形式が正しくありません"},tr:{base64:"Base64 olarak resim",file:"Dosya",errFileReaderNotSupported:"FileReader tarayıcınız tarafından desteklenmiyor.",errInvalidImage:"Geçersiz resim dosyası."},zh_tw:{base64:"圖片(base64編碼)",file:"檔案",errFileReaderNotSupported:"你的瀏覽器不支援FileReader",errInvalidImage:"不正確的檔案格式"},pt_br:{base64:"Imagem em base64",file:"Arquivo",errFileReaderNotSupported:"FileReader não é suportado pelo seu navegador.",errInvalidImage:"Arquivo de imagem inválido."},ko:{base64:"그림 넣기(base64)",file:"파일",errFileReaderNotSupported:"FileReader가 현재 브라우저를 지원하지 않습니다.",errInvalidImage:"유효하지 않은 파일"}},plugins:{base64:{shouldInit:a,init:function(i){var t={isSupported:a,fn:function(){i.saveRange();var a,t=i.openModalInsert(i.lang.base64,{file:{type:"file",required:!0,attributes:{accept:"image/*"}},alt:{label:"description",value:i.getRangeText()}},function(l){var n=new FileReader;n.onloadend=function(a){r(a.target.result)?(i.execCmd("insertImage",n.result,!1,!0),e(['img[src="',n.result,'"]:not([alt])'].join(""),i.$box).attr("alt",l.alt),i.closeModal()):i.addErrorOnModalField(e("input[type=file]",t),i.lang.errInvalidImage)},n.readAsDataURL(a)});e("input[type=file]").on("change",function(e){a=e.target.files[0]})}};i.addBtnDef("base64",t)}}}})}(jQuery); \ No newline at end of file diff --git a/assets/ext/trumbowyg/plugins/cleanpaste/trumbowyg.cleanpaste.js b/assets/ext/trumbowyg/plugins/cleanpaste/trumbowyg.cleanpaste.js new file mode 100644 index 00000000..86160547 --- /dev/null +++ b/assets/ext/trumbowyg/plugins/cleanpaste/trumbowyg.cleanpaste.js @@ -0,0 +1,111 @@ +/* =========================================================== + * trumbowyg.cleanpaste.js v1.0 + * Font Clean paste plugin for Trumbowyg + * http://alex-d.github.com/Trumbowyg + * =========================================================== + * Authors : Eric Radin + * Todd Graham (slackwalker) + * + * This plugin will perform a "cleaning" on any paste, in particular + * it will clean pasted content of microsoft word document tags and classes. + */ + +(function ($) { + 'use strict'; + + function checkValidTags(snippet) { + var theString = snippet; + + // Replace uppercase element names with lowercase + theString = theString.replace(/<[^> ]*/g, function (match) { + return match.toLowerCase(); + }); + + // Replace uppercase attribute names with lowercase + theString = theString.replace(/<[^>]*>/g, function (match) { + match = match.replace(/ [^=]+=/g, function (match2) { + return match2.toLowerCase(); + }); + return match; + }); + + // Put quotes around unquoted attributes + theString = theString.replace(/<[^>]*>/g, function (match) { + match = match.replace(/( [^=]+=)([^"][^ >]*)/g, '$1\"$2\"'); + return match; + }); + + return theString; + } + + function cleanIt(html) { + // first make sure all tags and attributes are made valid + html = checkValidTags(html); + + // Replace opening bold tags with strong + html = html.replace(/)/g, ')/g, ')/g, ')/g, '\s*/g, ''); + + // strip out   -cgCraft + html = html.replace(/ /gi, ' '); + // strip out extra spaces -cgCraft + html = html.replace(/ <\//gi, ']*>/g, function (match) { + match = match.replace(/ ([^=]+)="[^"]*"/g, function (match2, attributeName) { + if (['alt', 'href', 'src', 'title'].indexOf(attributeName) !== -1) { + return match2; + } + return ''; + }); + return match; + }); + + // Final clean out for MS Word crud + html = html.replace(/<\?xml[^>]*>/g, ''); + html = html.replace(/<[^ >]+:[^>]*>/g, ''); + html = html.replace(/<\/[^ >]+:[^>]*>/g, ''); + + // remove unwanted tags + html = html.replace(/<(div|span|style|meta|link).*?>/gi, ''); + + return html; + } + + // clean editor + // this will clean the inserted contents + // it does a compare, before and after paste to determine the + // pasted contents + $.extend(true, $.trumbowyg, { + plugins: { + cleanPaste: { + init: function (trumbowyg) { + trumbowyg.pasteHandlers.push(function () { + setTimeout(function () { + try { + trumbowyg.$ed.html(cleanIt(trumbowyg.$ed.html())); + } catch (c) { + } + }, 0); + }); + } + } + } + }); +})(jQuery); diff --git a/assets/ext/trumbowyg/plugins/cleanpaste/trumbowyg.cleanpaste.min.js b/assets/ext/trumbowyg/plugins/cleanpaste/trumbowyg.cleanpaste.min.js new file mode 100644 index 00000000..4c9b682e --- /dev/null +++ b/assets/ext/trumbowyg/plugins/cleanpaste/trumbowyg.cleanpaste.min.js @@ -0,0 +1 @@ +!function(e){"use strict";function r(e){var r=e;return r=r.replace(/<[^> ]*/g,function(e){return e.toLowerCase()}),r=r.replace(/<[^>]*>/g,function(e){return e=e.replace(/ [^=]+=/g,function(e){return e.toLowerCase()})}),r=r.replace(/<[^>]*>/g,function(e){return e=e.replace(/( [^=]+=)([^"][^ >]*)/g,'$1"$2"')})}function n(e){return e=r(e),e=e.replace(/)/g,")/g,")/g,")/g,"\s*/g,""),e=e.replace(/ /gi," "),e=e.replace(/ <\//gi,"]*>/g,function(e){return e=e.replace(/ ([^=]+)="[^"]*"/g,function(e,r){return["alt","href","src","title"].indexOf(r)!==-1?e:""})}),e=e.replace(/<\?xml[^>]*>/g,""),e=e.replace(/<[^ >]+:[^>]*>/g,""),e=e.replace(/<\/[^ >]+:[^>]*>/g,""),e=e.replace(/<(div|span|style|meta|link).*?>/gi,"")}e.extend(!0,e.trumbowyg,{plugins:{cleanPaste:{init:function(e){e.pasteHandlers.push(function(){setTimeout(function(){try{e.$ed.html(n(e.$ed.html()))}catch(r){}},0)})}}}})}(jQuery); \ No newline at end of file diff --git a/assets/ext/trumbowyg/plugins/colors/trumbowyg.colors.js b/assets/ext/trumbowyg/plugins/colors/trumbowyg.colors.js new file mode 100644 index 00000000..f01b95f2 --- /dev/null +++ b/assets/ext/trumbowyg/plugins/colors/trumbowyg.colors.js @@ -0,0 +1,250 @@ +/* =========================================================== + * trumbowyg.colors.js v1.2 + * Colors picker plugin for Trumbowyg + * http://alex-d.github.com/Trumbowyg + * =========================================================== + * Author : Alexandre Demode (Alex-D) + * Twitter : @AlexandreDemode + * Website : alex-d.fr + */ + +(function ($) { + 'use strict'; + + $.extend(true, $.trumbowyg, { + langs: { + // jshint camelcase:false + cs: { + foreColor: 'Barva textu', + backColor: 'Barva pozadí' + }, + en: { + foreColor: 'Text color', + backColor: 'Background color', + foreColorRemove: 'Remove text color', + backColorRemove: 'Remove background color' + }, + da: { + foreColor: 'Tekstfarve', + backColor: 'Baggrundsfarve' + }, + fr: { + foreColor: 'Couleur du texte', + backColor: 'Couleur de fond', + foreColorRemove: 'Supprimer la couleur du texte', + backColorRemove: 'Supprimer la couleur de fond' + }, + de: { + foreColor: 'Textfarbe', + backColor: 'Hintergrundfarbe' + }, + nl: { + foreColor: 'Tekstkleur', + backColor: 'Achtergrondkleur' + }, + sk: { + foreColor: 'Farba textu', + backColor: 'Farba pozadia' + }, + zh_cn: { + foreColor: '文字颜色', + backColor: '背景颜色' + }, + zh_tw: { + foreColor: '文字顏色', + backColor: '背景顏色' + }, + ru: { + foreColor: 'Цвет текста', + backColor: 'Цвет выделения текста' + }, + ja: { + foreColor: '文字色', + backColor: '背景色' + }, + tr: { + foreColor: 'Yazı rengi', + backColor: 'Arkaplan rengi' + }, + pt_br: { + foreColor: 'Cor de fonte', + backColor: 'Cor de fundo' + }, + ko: { + foreColor: '글자색', + backColor: '배경색', + foreColorRemove: '글자색 지우기', + backColorRemove: '배경색 지우기' + }, + } + }); + + // jshint camelcase:true + + + function hex(x) { + return ('0' + parseInt(x).toString(16)).slice(-2); + } + + function colorToHex(rgb) { + if (rgb.search('rgb') === -1) { + return rgb.replace('#', ''); + } else if (rgb === 'rgba(0, 0, 0, 0)') { + return 'transparent'; + } else { + rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/); + return hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]); + } + } + + function colorTagHandler(element, trumbowyg) { + var tags = []; + + if (!element.style) { + return tags; + } + + // background color + if (element.style.backgroundColor !== '') { + var backColor = colorToHex(element.style.backgroundColor); + if (trumbowyg.o.plugins.colors.colorList.indexOf(backColor) >= 0) { + tags.push('backColor' + backColor); + } else { + tags.push('backColorFree'); + } + } + + // text color + var foreColor; + if (element.style.color !== '') { + foreColor = colorToHex(element.style.color); + } else if (element.hasAttribute('color')) { + foreColor = colorToHex(element.getAttribute('color')); + } + if (foreColor) { + if (trumbowyg.o.plugins.colors.colorList.indexOf(foreColor) >= 0) { + tags.push('foreColor' + foreColor); + } else { + tags.push('foreColorFree'); + } + } + + return tags; + } + + var defaultOptions = { + colorList: [ + 'ffffff', '000000', 'eeece1', '1f497d', '4f81bd', 'c0504d', '9bbb59', '8064a2', '4bacc6', 'f79646', 'ffff00', + 'f2f2f2', '7f7f7f', 'ddd9c3', 'c6d9f0', 'dbe5f1', 'f2dcdb', 'ebf1dd', 'e5e0ec', 'dbeef3', 'fdeada', 'fff2ca', + 'd8d8d8', '595959', 'c4bd97', '8db3e2', 'b8cce4', 'e5b9b7', 'd7e3bc', 'ccc1d9', 'b7dde8', 'fbd5b5', 'ffe694', + 'bfbfbf', '3f3f3f', '938953', '548dd4', '95b3d7', 'd99694', 'c3d69b', 'b2a2c7', 'b7dde8', 'fac08f', 'f2c314', + 'a5a5a5', '262626', '494429', '17365d', '366092', '953734', '76923c', '5f497a', '92cddc', 'e36c09', 'c09100', + '7f7f7f', '0c0c0c', '1d1b10', '0f243e', '244061', '632423', '4f6128', '3f3151', '31859b', '974806', '7f6000' + ], + foreColorList: null, // fallbacks on colorList + backColorList: null, // fallbacks on colorList + allowCustomForeColor: true, + allowCustomBackColor: true, + displayAsList: false, + }; + + // Add all colors in two dropdowns + $.extend(true, $.trumbowyg, { + plugins: { + color: { + init: function (trumbowyg) { + trumbowyg.o.plugins.colors = trumbowyg.o.plugins.colors || defaultOptions; + var dropdownClass = trumbowyg.o.plugins.colors.displayAsList ? trumbowyg.o.prefix + 'dropdown--color-list' : ''; + + var foreColorBtnDef = { + dropdown: buildDropdown('foreColor', trumbowyg), + dropdownClass: dropdownClass, + }, + backColorBtnDef = { + dropdown: buildDropdown('backColor', trumbowyg), + dropdownClass: dropdownClass, + }; + + trumbowyg.addBtnDef('foreColor', foreColorBtnDef); + trumbowyg.addBtnDef('backColor', backColorBtnDef); + }, + tagHandler: colorTagHandler + } + } + }); + + function buildDropdown(fn, trumbowyg) { + var dropdown = [], + trumbowygColorOptions = trumbowyg.o.plugins.colors, + colorList = trumbowygColorOptions[fn + 'List'] || trumbowygColorOptions.colorList; + + $.each(colorList, function (i, color) { + var btn = fn + color, + btnDef = { + fn: fn, + forceCss: true, + hasIcon: false, + text: trumbowyg.lang['#' + color] || ('#' + color), + param: '#' + color, + style: 'background-color: #' + color + ';' + }; + + if (trumbowygColorOptions.displayAsList && fn === 'foreColor') { + btnDef.style = 'color: #' + color + ' !important;'; + } + + trumbowyg.addBtnDef(btn, btnDef); + dropdown.push(btn); + }); + + // Remove color + var removeColorButtonName = fn + 'Remove', + removeColorBtnDef = { + fn: 'removeFormat', + hasIcon: false, + param: fn, + style: 'background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAAG0lEQVQIW2NkQAAfEJMRmwBYhoGBYQtMBYoAADziAp0jtJTgAAAAAElFTkSuQmCC);' + }; + + if (trumbowygColorOptions.displayAsList) { + removeColorBtnDef.style = ''; + } + + trumbowyg.addBtnDef(removeColorButtonName, removeColorBtnDef); + dropdown.push(removeColorButtonName); + + // Custom color + if (trumbowygColorOptions['allowCustom' + fn.charAt(0).toUpperCase() + fn.substr(1)]) { + // add free color btn + var freeColorButtonName = fn + 'Free', + freeColorBtnDef = { + fn: function () { + trumbowyg.openModalInsert(trumbowyg.lang[fn], + { + color: { + label: fn, + forceCss: true, + type: 'color', + value: '#FFFFFF' + } + }, + // callback + function (values) { + trumbowyg.execCmd(fn, values.color); + return true; + } + ); + }, + hasIcon: false, + text: '#', + // style adjust for displaying the text + style: 'text-indent: 0; line-height: 20px; padding: 0 5px;' + }; + + trumbowyg.addBtnDef(freeColorButtonName, freeColorBtnDef); + dropdown.push(freeColorButtonName); + } + + return dropdown; + } +})(jQuery); diff --git a/assets/ext/trumbowyg/plugins/colors/trumbowyg.colors.min.js b/assets/ext/trumbowyg/plugins/colors/trumbowyg.colors.min.js new file mode 100644 index 00000000..841adffc --- /dev/null +++ b/assets/ext/trumbowyg/plugins/colors/trumbowyg.colors.min.js @@ -0,0 +1 @@ +!function(o){"use strict";function r(o){return("0"+parseInt(o).toString(16)).slice(-2)}function e(o){return o.search("rgb")===-1?o.replace("#",""):"rgba(0, 0, 0, 0)"===o?"transparent":(o=o.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/),r(o[1])+r(o[2])+r(o[3]))}function l(o,r){var l=[];if(!o.style)return l;if(""!==o.style.backgroundColor){var a=e(o.style.backgroundColor);r.o.plugins.colors.colorList.indexOf(a)>=0?l.push("backColor"+a):l.push("backColorFree")}var c;return""!==o.style.color?c=e(o.style.color):o.hasAttribute("color")&&(c=e(o.getAttribute("color"))),c&&(r.o.plugins.colors.colorList.indexOf(c)>=0?l.push("foreColor"+c):l.push("foreColorFree")),l}function a(r,e){var l=[],a=e.o.plugins.colors,c=a[r+"List"]||a.colorList;o.each(c,function(o,c){var f=r+c,t={fn:r,forceCss:!0,hasIcon:!1,text:e.lang["#"+c]||"#"+c,param:"#"+c,style:"background-color: #"+c+";"};a.displayAsList&&"foreColor"===r&&(t.style="color: #"+c+" !important;"),e.addBtnDef(f,t),l.push(f)});var f=r+"Remove",t={fn:"removeFormat",hasIcon:!1,param:r,style:"background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAAG0lEQVQIW2NkQAAfEJMRmwBYhoGBYQtMBYoAADziAp0jtJTgAAAAAElFTkSuQmCC);"};if(a.displayAsList&&(t.style=""),e.addBtnDef(f,t),l.push(f),a["allowCustom"+r.charAt(0).toUpperCase()+r.substr(1)]){var d=r+"Free",n={fn:function(){e.openModalInsert(e.lang[r],{color:{label:r,forceCss:!0,type:"color",value:"#FFFFFF"}},function(o){return e.execCmd(r,o.color),!0})},hasIcon:!1,text:"#",style:"text-indent: 0; line-height: 20px; padding: 0 5px;"};e.addBtnDef(d,n),l.push(d)}return l}o.extend(!0,o.trumbowyg,{langs:{cs:{foreColor:"Barva textu",backColor:"Barva pozadí"},en:{foreColor:"Text color",backColor:"Background color",foreColorRemove:"Remove text color",backColorRemove:"Remove background color"},da:{foreColor:"Tekstfarve",backColor:"Baggrundsfarve"},fr:{foreColor:"Couleur du texte",backColor:"Couleur de fond",foreColorRemove:"Supprimer la couleur du texte",backColorRemove:"Supprimer la couleur de fond"},de:{foreColor:"Textfarbe",backColor:"Hintergrundfarbe"},nl:{foreColor:"Tekstkleur",backColor:"Achtergrondkleur"},sk:{foreColor:"Farba textu",backColor:"Farba pozadia"},zh_cn:{foreColor:"文字颜色",backColor:"背景颜色"},zh_tw:{foreColor:"文字顏色",backColor:"背景顏色"},ru:{foreColor:"Цвет текста",backColor:"Цвет выделения текста"},ja:{foreColor:"文字色",backColor:"背景色"},tr:{foreColor:"Yazı rengi",backColor:"Arkaplan rengi"},pt_br:{foreColor:"Cor de fonte",backColor:"Cor de fundo"},ko:{foreColor:"글자색",backColor:"배경색",foreColorRemove:"글자색 지우기",backColorRemove:"배경색 지우기"}}});var c={colorList:["ffffff","000000","eeece1","1f497d","4f81bd","c0504d","9bbb59","8064a2","4bacc6","f79646","ffff00","f2f2f2","7f7f7f","ddd9c3","c6d9f0","dbe5f1","f2dcdb","ebf1dd","e5e0ec","dbeef3","fdeada","fff2ca","d8d8d8","595959","c4bd97","8db3e2","b8cce4","e5b9b7","d7e3bc","ccc1d9","b7dde8","fbd5b5","ffe694","bfbfbf","3f3f3f","938953","548dd4","95b3d7","d99694","c3d69b","b2a2c7","b7dde8","fac08f","f2c314","a5a5a5","262626","494429","17365d","366092","953734","76923c","5f497a","92cddc","e36c09","c09100","7f7f7f","0c0c0c","1d1b10","0f243e","244061","632423","4f6128","3f3151","31859b","974806","7f6000"],foreColorList:null,backColorList:null,allowCustomForeColor:!0,allowCustomBackColor:!0,displayAsList:!1};o.extend(!0,o.trumbowyg,{plugins:{color:{init:function(o){o.o.plugins.colors=o.o.plugins.colors||c;var r=o.o.plugins.colors.displayAsList?o.o.prefix+"dropdown--color-list":"",e={dropdown:a("foreColor",o),dropdownClass:r},l={dropdown:a("backColor",o),dropdownClass:r};o.addBtnDef("foreColor",e),o.addBtnDef("backColor",l)},tagHandler:l}}})}(jQuery); \ No newline at end of file diff --git a/assets/ext/trumbowyg/plugins/colors/ui/sass/trumbowyg.colors.scss b/assets/ext/trumbowyg/plugins/colors/ui/sass/trumbowyg.colors.scss new file mode 100644 index 00000000..a8c860a1 --- /dev/null +++ b/assets/ext/trumbowyg/plugins/colors/ui/sass/trumbowyg.colors.scss @@ -0,0 +1,68 @@ +/** + * Trumbowyg v2.21.0 - A lightweight WYSIWYG editor + * Default stylesheet for Trumbowyg editor plugin + * ------------------------ + * @link http://alex-d.github.io/Trumbowyg + * @license MIT + * @author Alexandre Demode (Alex-D) + * Twitter : @AlexandreDemode + * Website : alex-d.fr + */ + +.trumbowyg-dropdown-foreColor:not(.trumbowyg-dropdown--color-list), +.trumbowyg-dropdown-backColor:not(.trumbowyg-dropdown--color-list) { + max-width: 276px; + padding: 7px 5px; + overflow: initial; + + button { + display: block; + position: relative; + float: left; + text-indent: -9999px; + height: 20px; + width: 20px; + border: 1px solid #333; + padding: 0; + margin: 2px; + + &:hover, + &:focus { + &::after { + content: " "; + display: block; + position: absolute; + top: -5px; + left: -5px; + width: 27px; + height: 27px; + background: inherit; + border: 1px solid #fff; + box-shadow: #000 0 0 2px; + z-index: 10; + } + } + } +} + +.trumbowyg-dropdown-backColor.trumbowyg-dropdown--color-list { + button:not(.trumbowyg-backColorRemove-dropdown-button) { + position: relative; + color: #fff !important; + + &:hover, + &:focus { + &::after { + content: " "; + display: block; + position: absolute; + top: 13px; + left: 0; + width: 0; + height: 0; + border: 5px solid transparent; + border-left-color: #fff; + } + } + } +} diff --git a/assets/ext/trumbowyg/plugins/colors/ui/trumbowyg.colors.css b/assets/ext/trumbowyg/plugins/colors/ui/trumbowyg.colors.css new file mode 100644 index 00000000..ae10d4dc --- /dev/null +++ b/assets/ext/trumbowyg/plugins/colors/ui/trumbowyg.colors.css @@ -0,0 +1,55 @@ +/** + * Trumbowyg v2.21.0 - A lightweight WYSIWYG editor + * Trumbowyg plugin stylesheet + * ------------------------ + * @link http://alex-d.github.io/Trumbowyg + * @license MIT + * @author Alexandre Demode (Alex-D) + * Twitter : @AlexandreDemode + * Website : alex-d.fr + */ + +.trumbowyg-dropdown-foreColor:not(.trumbowyg-dropdown--color-list), +.trumbowyg-dropdown-backColor:not(.trumbowyg-dropdown--color-list) { + max-width: 276px; + padding: 7px 5px; + overflow: initial; } + .trumbowyg-dropdown-foreColor:not(.trumbowyg-dropdown--color-list) button, + .trumbowyg-dropdown-backColor:not(.trumbowyg-dropdown--color-list) button { + display: block; + position: relative; + float: left; + text-indent: -9999px; + height: 20px; + width: 20px; + border: 1px solid #333; + padding: 0; + margin: 2px; } + .trumbowyg-dropdown-foreColor:not(.trumbowyg-dropdown--color-list) button:hover::after, .trumbowyg-dropdown-foreColor:not(.trumbowyg-dropdown--color-list) button:focus::after, + .trumbowyg-dropdown-backColor:not(.trumbowyg-dropdown--color-list) button:hover::after, + .trumbowyg-dropdown-backColor:not(.trumbowyg-dropdown--color-list) button:focus::after { + content: " "; + display: block; + position: absolute; + top: -5px; + left: -5px; + width: 27px; + height: 27px; + background: inherit; + border: 1px solid #fff; + box-shadow: #000 0 0 2px; + z-index: 10; } + +.trumbowyg-dropdown-backColor.trumbowyg-dropdown--color-list button:not(.trumbowyg-backColorRemove-dropdown-button) { + position: relative; + color: #fff !important; } + .trumbowyg-dropdown-backColor.trumbowyg-dropdown--color-list button:not(.trumbowyg-backColorRemove-dropdown-button):hover::after, .trumbowyg-dropdown-backColor.trumbowyg-dropdown--color-list button:not(.trumbowyg-backColorRemove-dropdown-button):focus::after { + content: " "; + display: block; + position: absolute; + top: 13px; + left: 0; + width: 0; + height: 0; + border: 5px solid transparent; + border-left-color: #fff; } diff --git a/assets/ext/trumbowyg/plugins/colors/ui/trumbowyg.colors.min.css b/assets/ext/trumbowyg/plugins/colors/ui/trumbowyg.colors.min.css new file mode 100644 index 00000000..9354743e --- /dev/null +++ b/assets/ext/trumbowyg/plugins/colors/ui/trumbowyg.colors.min.css @@ -0,0 +1,2 @@ +/** Trumbowyg v2.21.0 - A lightweight WYSIWYG editor - alex-d.github.io/Trumbowyg - License MIT - Author : Alexandre Demode (Alex-D) / alex-d.fr */ +.trumbowyg-dropdown-backColor:not(.trumbowyg-dropdown--color-list),.trumbowyg-dropdown-foreColor:not(.trumbowyg-dropdown--color-list){max-width:276px;padding:7px 5px;overflow:initial}.trumbowyg-dropdown-backColor:not(.trumbowyg-dropdown--color-list) button,.trumbowyg-dropdown-foreColor:not(.trumbowyg-dropdown--color-list) button{display:block;position:relative;float:left;text-indent:-9999px;height:20px;width:20px;border:1px solid #333;padding:0;margin:2px}.trumbowyg-dropdown-backColor:not(.trumbowyg-dropdown--color-list) button:focus::after,.trumbowyg-dropdown-backColor:not(.trumbowyg-dropdown--color-list) button:hover::after,.trumbowyg-dropdown-foreColor:not(.trumbowyg-dropdown--color-list) button:focus::after,.trumbowyg-dropdown-foreColor:not(.trumbowyg-dropdown--color-list) button:hover::after{content:" ";display:block;position:absolute;top:-5px;left:-5px;width:27px;height:27px;background:inherit;border:1px solid #fff;box-shadow:#000 0 0 2px;z-index:10}.trumbowyg-dropdown-backColor.trumbowyg-dropdown--color-list button:not(.trumbowyg-backColorRemove-dropdown-button){position:relative;color:#fff!important}.trumbowyg-dropdown-backColor.trumbowyg-dropdown--color-list button:not(.trumbowyg-backColorRemove-dropdown-button):focus::after,.trumbowyg-dropdown-backColor.trumbowyg-dropdown--color-list button:not(.trumbowyg-backColorRemove-dropdown-button):hover::after{content:" ";display:block;position:absolute;top:13px;left:0;width:0;height:0;border:5px solid transparent;border-left-color:#fff} \ No newline at end of file diff --git a/assets/ext/trumbowyg/plugins/emoji/trumbowyg.emoji.js b/assets/ext/trumbowyg/plugins/emoji/trumbowyg.emoji.js new file mode 100644 index 00000000..d4b456b3 --- /dev/null +++ b/assets/ext/trumbowyg/plugins/emoji/trumbowyg.emoji.js @@ -0,0 +1,1353 @@ +/* =========================================================== + * trumbowyg.emoji.js v0.1 + * Emoji picker plugin for Trumbowyg + * http://alex-d.github.com/Trumbowyg + * =========================================================== + * Author : Nicolas Pion + * Twitter : @nicolas_pion + */ + +(function ($) { + 'use strict'; + + var defaultOptions = { + emojiList: [ + '⁉', + '™', + 'ℹ', + '↔', + '↕', + '↖', + '↗', + '↘', + '↙', + '⌨', + '☀', + '☁', + '☂', + '☃', + '☄', + '☑', + '☔', + '☕', + '☘', + '☠', + '☢', + '☣', + '☦', + '☸', + '☹', + '♀', + '♂', + '♈', + '♉', + '♐', + '♑', + '♒', + '♓', + '♠', + '♣', + '♥', + '♦', + '♨', + '⚒', + '⚓', + '⚔', + '⚕', + '⚖', + '⚗', + '⚙', + '✂', + '✅', + '✈', + '✉', + '✒', + '✔', + '✖', + '✡', + '✨', + '✳', + '✴', + '❄', + '❇', + '❓', + '❔', + '❕', + '❗', + '❣', + '❤', + '➕', + '➖', + '➗', + '⤴', + '⤵', + '〰', + '㊗', + '㊙', + '🧡', + '💛', + '💚', + '💙', + '💜', + '🖤', + '💔', + '💕', + '💞', + '💓', + '💗', + '💖', + '💘', + '💝', + '💟', + '☮', + '✝', + '☪', + '🕉', + '🔯', + '🕎', + '☯', + '🛐', + '⛎', + '♊', + '♋', + '♌', + '♍', + '♎', + '♏', + '🆔', + '⚛', + '♾', + '🉑', + '📴', + '📳', + '🈶', + '🈚', + '🈸', + '🈺', + '🈷', + '🆚', + '💮', + '🉐', + '🈴', + '🈵', + '🈹', + '🈲', + '🅰', + '🅱', + '🆎', + '🆑', + '🅾', + '🆘', + '❌', + '⭕', + '🛑', + '⛔', + '📛', + '🚫', + '💯', + '💢', + '🚷', + '🚯', + '🚳', + '🚱', + '🔞', + '📵', + '🚭', + '‼', + '🔅', + '🔆', + '〽', + '⚠', + '🚸', + '🔱', + '⚜', + '🔰', + '♻', + '🈯', + '💹', + '❎', + '🌐', + '💠', + 'Ⓜ', + '🌀', + '💤', + '🏧', + '🚾', + '♿', + '🅿', + '🈳', + '🈂', + '🛂', + '🛃', + '🛄', + '🛅', + '🚹', + '🚺', + '🚼', + '🚻', + '🚮', + '🎦', + '📶', + '🈁', + '🔣', + '🔤', + '🔡', + '🔠', + '🆖', + '🆗', + '🆙', + '🆒', + '🆕', + '🆓', + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '🔟', + '🔢', + '#', + '*', + '⏏', + '▶', + '⏸', + '⏯', + '⏹', + '⏺', + '⏭', + '⏮', + '⏩', + '⏪', + '⏫', + '⏬', + '◀', + '🔼', + '🔽', + '➡', + '⬅', + '⬆', + '⬇', + '↪', + '↩', + '🔀', + '🔁', + '🔂', + '🔄', + '🔃', + '🎵', + '🎶', + '💲', + '💱', + '©', + '®', + '➰', + '➿', + '🔚', + '🔙', + '🔛', + '🔝', + '🔜', + '🔘', + '⚪', + '⚫', + '🔴', + '🔵', + '🔺', + '🔻', + '🔸', + '🔹', + '🔶', + '🔷', + '🔳', + '🔲', + '▪', + '▫', + '◾', + '◽', + '◼', + '◻', + '⬛', + '⬜', + '🔈', + '🔇', + '🔉', + '🔊', + '🔔', + '🔕', + '📣', + '📢', + '🗨', + '👁', + '💬', + '💭', + '🗯', + '🃏', + '🎴', + '🀄', + '🕐', + '🕑', + '🕒', + '🕓', + '🕔', + '🕕', + '🕖', + '🕗', + '🕘', + '🕙', + '🕚', + '🕛', + '🕜', + '🕝', + '🕞', + '🕟', + '🕠', + '🕡', + '🕢', + '🕣', + '🕤', + '🕥', + '🕦', + '🕧', + '⚽', + '🏀', + '🏈', + '⚾', + '🥎', + '🎾', + '🏐', + '🏉', + '🎱', + '🏓', + '🏸', + '🥅', + '🏒', + '🏑', + '🏏', + '🥍', + '⛳', + '🥏', + '🏹', + '🎣', + '🥊', + '🥋', + '🎽', + '🛹', + '⛸', + '🥌', + '🛷', + '🎿', + '⛷', + '🏂', + '🏋', + '🤼', + '🤸', + '⛹', + '🤺', + '🤾', + '🏌', + '🏇', + '🧘', + '🏄', + '🏊', + '🤽', + '🚣', + '🧗', + '🚵', + '🚴', + '🏆', + '🥇', + '🥈', + '🥉', + '🏅', + '🎖', + '🏵', + '🎗', + '🎫', + '🎟', + '🎪', + '🤹', + '🎭', + '🎨', + '🎬', + '🎤', + '🎧', + '🎼', + '🎹', + '🥁', + '🎷', + '🎺', + '🎸', + '🎻', + '🎲', + '🎯', + '🎳', + '🎮', + '🎰', + '⌚', + '📱', + '📲', + '💻', + '🖥', + '🖨', + '🖱', + '🖲', + '🕹', + '♟', + '🧩', + '🗜', + '💽', + '💾', + '💿', + '📀', + '📼', + '📷', + '📸', + '📹', + '🎥', + '📽', + '🎞', + '📞', + '☎', + '📟', + '📠', + '📺', + '📻', + '🎙', + '🎚', + '🎛', + '⏱', + '⏲', + '⏰', + '🕰', + '⌛', + '⏳', + '📡', + '🧭', + '🔋', + '🔌', + '🧲', + '💡', + '🔦', + '🕯', + '🧯', + '🗑', + '🛢', + '💸', + '💵', + '💴', + '💶', + '💷', + '💰', + '💳', + '💎', + '🧿', + '🧱', + '🧰', + '🔧', + '🔨', + '🛠', + '⛏', + '🔩', + '⛓', + '🔫', + '💣', + '🔪', + '🗡', + '🛡', + '🚬', + '⚰', + '⚱', + '🏺', + '🔮', + '📿', + '💈', + '🧪', + '🧫', + '🧬', + '🧮', + '🔭', + '🔬', + '🕳', + '💊', + '💉', + '🌡', + '🚽', + '🚰', + '🚿', + '🛁', + '🛀', + '🧹', + '🧺', + '🧻', + '🧼', + '🧽', + '🧴', + '🧵', + '🧶', + '🛎', + '🔑', + '🗝', + '🚪', + '🛋', + '🛏', + '🛌', + '🧸', + '🖼', + '🛍', + '🛒', + '🎁', + '🎈', + '🎏', + '🎀', + '🎊', + '🎉', + '🎎', + '🏮', + '🎐', + '🧧', + '📩', + '📨', + '📧', + '💌', + '📥', + '📤', + '📦', + '🏷', + '📪', + '📫', + '📬', + '📭', + '📮', + '📯', + '📜', + '📃', + '📄', + '🧾', + '📑', + '📊', + '📈', + '📉', + '🗒', + '🗓', + '📆', + '📅', + '📇', + '🗃', + '🗳', + '🗄', + '📋', + '📁', + '📂', + '🗂', + '🗞', + '📰', + '📓', + '📔', + '📒', + '📕', + '📗', + '📘', + '📙', + '📚', + '📖', + '🔖', + '🔗', + '📎', + '🖇', + '📐', + '📏', + '🧷', + '📌', + '📍', + '🖊', + '🖋', + '🖌', + '🖍', + '📝', + '✏', + '🔍', + '🔎', + '🔏', + '🔐', + '🐶', + '🐱', + '🐭', + '🐹', + '🐰', + '🦊', + '🦝', + '🐻', + '🐼', + '🦘', + '🦡', + '🐨', + '🐯', + '🦁', + '🐮', + '🐷', + '🐽', + '🐸', + '🐵', + '🙈', + '🙉', + '🙊', + '🐒', + '🐔', + '🐧', + '🐦', + '🐤', + '🐣', + '🐥', + '🦆', + '🦢', + '🦅', + '🦉', + '🦜', + '🦚', + '🦇', + '🐺', + '🐗', + '🐴', + '🦄', + '🐝', + '🐛', + '🦋', + '🐌', + '🐚', + '🐞', + '🐜', + '🦗', + '🕷', + '🕸', + '🦂', + '🦟', + '🦠', + '🐢', + '🐍', + '🦎', + '🦖', + '🦕', + '🐙', + '🦑', + '🦐', + '🦀', + '🦞', + '🐡', + '🐠', + '🐟', + '🐬', + '🐳', + '🐋', + '🦈', + '🐊', + '🐅', + '🐆', + '🦓', + '🦍', + '🐘', + '🦏', + '🦛', + '🐪', + '🐫', + '🦒', + '🦙', + '🐃', + '🐂', + '🐄', + '🐎', + '🐖', + '🐏', + '🐑', + '🐐', + '🦌', + '🐕', + '🐩', + '🐈', + '🐓', + '🦃', + '🕊', + '🐇', + '🐁', + '🐀', + '🐿', + '🦔', + '🐾', + '🐉', + '🐲', + '🌵', + '🎄', + '🌲', + '🌳', + '🌴', + '🌱', + '🌿', + '🍀', + '🎍', + '🎋', + '🍃', + '🍂', + '🍁', + '🍄', + '🌾', + '💐', + '🌷', + '🌹', + '🥀', + '🌺', + '🌸', + '🌼', + '🌻', + '🌞', + '🌝', + '🌛', + '🌜', + '🌚', + '🌕', + '🌖', + '🌗', + '🌘', + '🌑', + '🌒', + '🌓', + '🌔', + '🌙', + '🌎', + '🌍', + '🌏', + '💫', + '⭐', + '🌟', + '⚡', + '💥', + '🔥', + '🌪', + '🌈', + '🌤', + '⛅', + '🌥', + '🌦', + '🌧', + '⛈', + '🌩', + '🌨', + '⛄', + '🌬', + '💨', + '💧', + '💦', + '🌊', + '🌫', + '🍏', + '🍎', + '🍐', + '🍊', + '🍋', + '🍌', + '🍉', + '🍇', + '🍓', + '🍈', + '🍒', + '🍑', + '🥭', + '🍍', + '🥥', + '🥝', + '🍅', + '🍆', + '🥑', + '🥦', + '🥬', + '🥒', + '🌶', + '🌽', + '🥕', + '🥔', + '🍠', + '🥐', + '🍞', + '🥖', + '🥨', + '🥯', + '🧀', + '🥚', + '🍳', + '🥞', + '🥓', + '🥩', + '🍗', + '🍖', + '🌭', + '🍔', + '🍟', + '🍕', + '🥪', + '🥙', + '🌮', + '🌯', + '🥗', + '🥘', + '🥫', + '🍝', + '🍜', + '🍲', + '🍛', + '🍣', + '🍱', + '🍤', + '🍙', + '🍚', + '🍘', + '🍥', + '🥠', + '🍢', + '🍡', + '🍧', + '🍨', + '🍦', + '🥧', + '🍰', + '🎂', + '🥮', + '🧁', + '🍮', + '🍭', + '🍬', + '🍫', + '🍿', + '🧂', + '🍩', + '🥟', + '🍪', + '🌰', + '🥜', + '🍯', + '🥛', + '🍼', + '🍵', + '🥤', + '🍶', + '🍺', + '🍻', + '🥂', + '🍷', + '🥃', + '🍸', + '🍹', + '🍾', + '🥄', + '🍴', + '🍽', + '🥣', + '🥡', + '🥢', + '😀', + '😃', + '😄', + '😁', + '😆', + '😅', + '😂', + '🤣', + '☺', + '😊', + '😇', + '🙂', + '🙃', + '😉', + '😌', + '😍', + '😘', + '🥰', + '😗', + '😙', + '😚', + '😋', + '😛', + '😝', + '😜', + '🤪', + '🤨', + '🧐', + '🤓', + '😎', + '🤩', + '🥳', + '😏', + '😒', + '😞', + '😔', + '😟', + '😕', + '🙁', + '😣', + '😖', + '😫', + '😩', + '😢', + '😭', + '😤', + '😠', + '😡', + '🤬', + '🤯', + '😳', + '😱', + '😨', + '😰', + '🥵', + '🥶', + '🥺', + '😥', + '😓', + '🤗', + '🤔', + '🤭', + '🤫', + '🤥', + '😶', + '😐', + '😑', + '😬', + '🙄', + '😯', + '😦', + '😧', + '😮', + '😲', + '😴', + '🤤', + '😪', + '😵', + '🤐', + '🥴', + '🤢', + '🤮', + '🤧', + '😷', + '🤒', + '🤕', + '🤑', + '🤠', + '😈', + '👿', + '👹', + '👺', + '🤡', + '💩', + '👻', + '💀', + '👽', + '👾', + '🤖', + '🎃', + '😺', + '😸', + '😹', + '😻', + '😼', + '😽', + '🙀', + '😿', + '😾', + '🤲', + '👐', + '🙌', + '👏', + '🤝', + '👍', + '👎', + '👊', + '✊', + '🤛', + '🤜', + '🤞', + '✌', + '🤟', + '🤘', + '👌', + '👈', + '👉', + '👆', + '👇', + '☝', + '✋', + '🤚', + '🖐', + '🖖', + '👋', + '🤙', + '💪', + '🦵', + '🦶', + '🖕', + '✍', + '🙏', + '💍', + '💄', + '💋', + '👄', + '👅', + '👂', + '👃', + '👣', + '👀', + '🧠', + '🦴', + '🦷', + '🗣', + '👤', + '👥', + '👶', + '👧', + '🧒', + '👦', + '👩', + '🧑', + '👨', + '👱', + '🧔', + '👵', + '🧓', + '👴', + '👲', + '👳', + '🧕', + '👮', + '👷', + '💂', + '🕵', + '👰', + '🤵', + '👸', + '🤴', + '🤶', + '🎅', + '🦸', + '🦹', + '🧙', + '🧝', + '🧛', + '🧟', + '🧞', + '🧜', + '🧚', + '👼', + '🤰', + '🤱', + '🙇', + '💁', + '🙅', + '🙆', + '🙋', + '🤦', + '🤷', + '🙎', + '🙍', + '💇', + '💆', + '🧖', + '💅', + '🤳', + '💃', + '🕺', + '👯', + '🕴', + '🚶', + '🏃', + '👫', + '👭', + '👬', + '💑', + '💏', + '👪', + '🧥', + '👚', + '👕', + '👖', + '👔', + '👗', + '👙', + '👘', + '🥼', + '👠', + '👡', + '👢', + '👞', + '👟', + '🥾', + '🥿', + '🧦', + '🧤', + '🧣', + '🎩', + '🧢', + '👒', + '🎓', + '⛑', + '👑', + '👝', + '👛', + '👜', + '💼', + '🎒', + '👓', + '🕶', + '🥽', + '🌂', + '🦰', + '🦱', + '🦳', + '🦲', + '🇿', + '🇾', + '🇽', + '🇼', + '🇻', + '🇺', + '🇹', + '🇸', + '🇷', + '🇶', + '🇵', + '🇴', + '🇳', + '🇲', + '🇱', + '🇰', + '🇯', + '🇮', + '🇭', + '🇬', + '🇫', + '🇪', + '🇩', + '🇨', + '🇧', + '🇦', + '🚗', + '🚕', + '🚙', + '🚌', + '🚎', + '🏎', + '🚓', + '🚑', + '🚒', + '🚐', + '🚚', + '🚛', + '🚜', + '🛴', + '🚲', + '🛵', + '🏍', + '🚨', + '🚔', + '🚍', + '🚘', + '🚖', + '🚡', + '🚠', + '🚟', + '🚃', + '🚋', + '🚞', + '🚝', + '🚄', + '🚅', + '🚈', + '🚂', + '🚆', + '🚇', + '🚊', + '🚉', + '🛫', + '🛬', + '🛩', + '💺', + '🧳', + '🛰', + '🚀', + '🛸', + '🚁', + '🛶', + '⛵', + '🚤', + '🛥', + '🛳', + '⛴', + '🚢', + '⛽', + '🚧', + '🚦', + '🚥', + '🚏', + '🗺', + '🗿', + '🗽', + '🗼', + '🏰', + '🏯', + '🏟', + '🎡', + '🎢', + '🎠', + '⛲', + '⛱', + '🏖', + '🏝', + '🏜', + '🌋', + '⛰', + '🏔', + '🗻', + '🏕', + '⛺', + '🏠', + '🏡', + '🏘', + '🏚', + '🏗', + '🏭', + '🏢', + '🏬', + '🏣', + '🏤', + '🏥', + '🏦', + '🏨', + '🏪', + '🏫', + '🏩', + '💒', + '🏛', + '⛪', + '🕌', + '🕍', + '🕋', + '⛩', + '🛤', + '🛣', + '🗾', + '🎑', + '🏞', + '🌅', + '🌄', + '🌠', + '🎇', + '🎆', + '🧨', + '🌇', + '🌆', + '🏙', + '🌃', + '🌌', + '🌉', + '🔒', + '🔓', + '🌁', + '🏳', + '🏴', + '🏁', + '🚩', + '🎌', + '🏻', + '🏼', + '🏽', + '🏾', + '🏿' + ] + }; + + // Add all emoji in a dropdown + $.extend(true, $.trumbowyg, { + langs: { + // jshint camelcase:false + en: { + emoji: 'Add an emoji' + }, + da: { + emoji: 'Tilføj et humørikon' + }, + de: { + emoji: 'Emoticon einfügen' + }, + fr: { + emoji: 'Ajouter un emoji' + }, + zh_cn: { + emoji: '添加表情' + }, + ru: { + emoji: 'Вставить emoji' + }, + ja: { + emoji: '絵文字の挿入' + }, + tr: { + emoji: 'Emoji ekle' + }, + ko: { + emoji: '이모지 넣기' + }, + }, + // jshint camelcase:true + plugins: { + emoji: { + init: function (trumbowyg) { + trumbowyg.o.plugins.emoji = trumbowyg.o.plugins.emoji || defaultOptions; + var emojiBtnDef = { + dropdown: buildDropdown(trumbowyg) + }; + trumbowyg.addBtnDef('emoji', emojiBtnDef); + } + } + } + }); + + function buildDropdown(trumbowyg) { + var dropdown = []; + + $.each(trumbowyg.o.plugins.emoji.emojiList, function (i, emoji) { + if ($.isArray(emoji)) { // Custom emoji behaviour + var emojiCode = emoji[0], + emojiUrl = emoji[1], + emojiHtml = '' + emojiCode + '', + customEmojiBtnName = 'emoji-' + emojiCode.replace(/:/g, ''), + customEmojiBtnDef = { + hasIcon: false, + text: emojiHtml, + fn: function () { + trumbowyg.execCmd('insertImage', emojiUrl, false, true); + return true; + } + }; + + trumbowyg.addBtnDef(customEmojiBtnName, customEmojiBtnDef); + dropdown.push(customEmojiBtnName); + } else { // Default behaviour + var btn = emoji.replace(/:/g, ''), + defaultEmojiBtnName = 'emoji-' + btn, + defaultEmojiBtnDef = { + text: emoji, + fn: function () { + var encodedEmoji = String.fromCodePoint(emoji.replace('&#', '0')); + trumbowyg.execCmd('insertText', encodedEmoji); + return true; + } + }; + + trumbowyg.addBtnDef(defaultEmojiBtnName, defaultEmojiBtnDef); + dropdown.push(defaultEmojiBtnName); + } + }); + + return dropdown; + } +})(jQuery); diff --git a/assets/ext/trumbowyg/plugins/emoji/trumbowyg.emoji.min.js b/assets/ext/trumbowyg/plugins/emoji/trumbowyg.emoji.min.js new file mode 100644 index 00000000..3ba21406 --- /dev/null +++ b/assets/ext/trumbowyg/plugins/emoji/trumbowyg.emoji.min.js @@ -0,0 +1 @@ +!function(x){"use strict";function F(F){var E=[];return x.each(F.o.plugins.emoji.emojiList,function(B,A){if(x.isArray(A)){var D=A[0],C=A[1],e=''+D+'',i="emoji-"+D.replace(/:/g,""),o={hasIcon:!1,text:e,fn:function(){return F.execCmd("insertImage",C,!1,!0),!0}};F.addBtnDef(i,o),E.push(i)}else{var n=A.replace(/:/g,""),t="emoji-"+n,r={text:A,fn:function(){var x=String.fromCodePoint(A.replace("&#","0"));return F.execCmd("insertText",x),!0}};F.addBtnDef(t,r),E.push(t)}}),E}var E={emojiList:["⁉","™","ℹ","↔","↕","↖","↗","↘","↙","⌨","☀","☁","☂","☃","☄","☑","☔","☕","☘","☠","☢","☣","☦","☸","☹","♀","♂","♈","♉","♐","♑","♒","♓","♠","♣","♥","♦","♨","⚒","⚓","⚔","⚕","⚖","⚗","⚙","✂","✅","✈","✉","✒","✔","✖","✡","✨","✳","✴","❄","❇","❓","❔","❕","❗","❣","❤","➕","➖","➗","⤴","⤵","〰","㊗","㊙","🧡","💛","💚","💙","💜","🖤","💔","💕","💞","💓","💗","💖","💘","💝","💟","☮","✝","☪","🕉","🔯","🕎","☯","🛐","⛎","♊","♋","♌","♍","♎","♏","🆔","⚛","♾","🉑","📴","📳","🈶","🈚","🈸","🈺","🈷","🆚","💮","🉐","🈴","🈵","🈹","🈲","🅰","🅱","🆎","🆑","🅾","🆘","❌","⭕","🛑","⛔","📛","🚫","💯","💢","🚷","🚯","🚳","🚱","🔞","📵","🚭","‼","🔅","🔆","〽","⚠","🚸","🔱","⚜","🔰","♻","🈯","💹","❎","🌐","💠","Ⓜ","🌀","💤","🏧","🚾","♿","🅿","🈳","🈂","🛂","🛃","🛄","🛅","🚹","🚺","🚼","🚻","🚮","🎦","📶","🈁","🔣","🔤","🔡","🔠","🆖","🆗","🆙","🆒","🆕","🆓","0","1","2","3","4","5","6","7","8","9","🔟","🔢","#","*","⏏","▶","⏸","⏯","⏹","⏺","⏭","⏮","⏩","⏪","⏫","⏬","◀","🔼","🔽","➡","⬅","⬆","⬇","↪","↩","🔀","🔁","🔂","🔄","🔃","🎵","🎶","💲","💱","©","®","➰","➿","🔚","🔙","🔛","🔝","🔜","🔘","⚪","⚫","🔴","🔵","🔺","🔻","🔸","🔹","🔶","🔷","🔳","🔲","▪","▫","◾","◽","◼","◻","⬛","⬜","🔈","🔇","🔉","🔊","🔔","🔕","📣","📢","🗨","👁","💬","💭","🗯","🃏","🎴","🀄","🕐","🕑","🕒","🕓","🕔","🕕","🕖","🕗","🕘","🕙","🕚","🕛","🕜","🕝","🕞","🕟","🕠","🕡","🕢","🕣","🕤","🕥","🕦","🕧","⚽","🏀","🏈","⚾","🥎","🎾","🏐","🏉","🎱","🏓","🏸","🥅","🏒","🏑","🏏","🥍","⛳","🥏","🏹","🎣","🥊","🥋","🎽","🛹","⛸","🥌","🛷","🎿","⛷","🏂","🏋","🤼","🤸","⛹","🤺","🤾","🏌","🏇","🧘","🏄","🏊","🤽","🚣","🧗","🚵","🚴","🏆","🥇","🥈","🥉","🏅","🎖","🏵","🎗","🎫","🎟","🎪","🤹","🎭","🎨","🎬","🎤","🎧","🎼","🎹","🥁","🎷","🎺","🎸","🎻","🎲","🎯","🎳","🎮","🎰","⌚","📱","📲","💻","🖥","🖨","🖱","🖲","🕹","♟","🧩","🗜","💽","💾","💿","📀","📼","📷","📸","📹","🎥","📽","🎞","📞","☎","📟","📠","📺","📻","🎙","🎚","🎛","⏱","⏲","⏰","🕰","⌛","⏳","📡","🧭","🔋","🔌","🧲","💡","🔦","🕯","🧯","🗑","🛢","💸","💵","💴","💶","💷","💰","💳","💎","🧿","🧱","🧰","🔧","🔨","🛠","⛏","🔩","⛓","🔫","💣","🔪","🗡","🛡","🚬","⚰","⚱","🏺","🔮","📿","💈","🧪","🧫","🧬","🧮","🔭","🔬","🕳","💊","💉","🌡","🚽","🚰","🚿","🛁","🛀","🧹","🧺","🧻","🧼","🧽","🧴","🧵","🧶","🛎","🔑","🗝","🚪","🛋","🛏","🛌","🧸","🖼","🛍","🛒","🎁","🎈","🎏","🎀","🎊","🎉","🎎","🏮","🎐","🧧","📩","📨","📧","💌","📥","📤","📦","🏷","📪","📫","📬","📭","📮","📯","📜","📃","📄","🧾","📑","📊","📈","📉","🗒","🗓","📆","📅","📇","🗃","🗳","🗄","📋","📁","📂","🗂","🗞","📰","📓","📔","📒","📕","📗","📘","📙","📚","📖","🔖","🔗","📎","🖇","📐","📏","🧷","📌","📍","🖊","🖋","🖌","🖍","📝","✏","🔍","🔎","🔏","🔐","🐶","🐱","🐭","🐹","🐰","🦊","🦝","🐻","🐼","🦘","🦡","🐨","🐯","🦁","🐮","🐷","🐽","🐸","🐵","🙈","🙉","🙊","🐒","🐔","🐧","🐦","🐤","🐣","🐥","🦆","🦢","🦅","🦉","🦜","🦚","🦇","🐺","🐗","🐴","🦄","🐝","🐛","🦋","🐌","🐚","🐞","🐜","🦗","🕷","🕸","🦂","🦟","🦠","🐢","🐍","🦎","🦖","🦕","🐙","🦑","🦐","🦀","🦞","🐡","🐠","🐟","🐬","🐳","🐋","🦈","🐊","🐅","🐆","🦓","🦍","🐘","🦏","🦛","🐪","🐫","🦒","🦙","🐃","🐂","🐄","🐎","🐖","🐏","🐑","🐐","🦌","🐕","🐩","🐈","🐓","🦃","🕊","🐇","🐁","🐀","🐿","🦔","🐾","🐉","🐲","🌵","🎄","🌲","🌳","🌴","🌱","🌿","🍀","🎍","🎋","🍃","🍂","🍁","🍄","🌾","💐","🌷","🌹","🥀","🌺","🌸","🌼","🌻","🌞","🌝","🌛","🌜","🌚","🌕","🌖","🌗","🌘","🌑","🌒","🌓","🌔","🌙","🌎","🌍","🌏","💫","⭐","🌟","⚡","💥","🔥","🌪","🌈","🌤","⛅","🌥","🌦","🌧","⛈","🌩","🌨","⛄","🌬","💨","💧","💦","🌊","🌫","🍏","🍎","🍐","🍊","🍋","🍌","🍉","🍇","🍓","🍈","🍒","🍑","🥭","🍍","🥥","🥝","🍅","🍆","🥑","🥦","🥬","🥒","🌶","🌽","🥕","🥔","🍠","🥐","🍞","🥖","🥨","🥯","🧀","🥚","🍳","🥞","🥓","🥩","🍗","🍖","🌭","🍔","🍟","🍕","🥪","🥙","🌮","🌯","🥗","🥘","🥫","🍝","🍜","🍲","🍛","🍣","🍱","🍤","🍙","🍚","🍘","🍥","🥠","🍢","🍡","🍧","🍨","🍦","🥧","🍰","🎂","🥮","🧁","🍮","🍭","🍬","🍫","🍿","🧂","🍩","🥟","🍪","🌰","🥜","🍯","🥛","🍼","🍵","🥤","🍶","🍺","🍻","🥂","🍷","🥃","🍸","🍹","🍾","🥄","🍴","🍽","🥣","🥡","🥢","😀","😃","😄","😁","😆","😅","😂","🤣","☺","😊","😇","🙂","🙃","😉","😌","😍","😘","🥰","😗","😙","😚","😋","😛","😝","😜","🤪","🤨","🧐","🤓","😎","🤩","🥳","😏","😒","😞","😔","😟","😕","🙁","😣","😖","😫","😩","😢","😭","😤","😠","😡","🤬","🤯","😳","😱","😨","😰","🥵","🥶","🥺","😥","😓","🤗","🤔","🤭","🤫","🤥","😶","😐","😑","😬","🙄","😯","😦","😧","😮","😲","😴","🤤","😪","😵","🤐","🥴","🤢","🤮","🤧","😷","🤒","🤕","🤑","🤠","😈","👿","👹","👺","🤡","💩","👻","💀","👽","👾","🤖","🎃","😺","😸","😹","😻","😼","😽","🙀","😿","😾","🤲","👐","🙌","👏","🤝","👍","👎","👊","✊","🤛","🤜","🤞","✌","🤟","🤘","👌","👈","👉","👆","👇","☝","✋","🤚","🖐","🖖","👋","🤙","💪","🦵","🦶","🖕","✍","🙏","💍","💄","💋","👄","👅","👂","👃","👣","👀","🧠","🦴","🦷","🗣","👤","👥","👶","👧","🧒","👦","👩","🧑","👨","👱","🧔","👵","🧓","👴","👲","👳","🧕","👮","👷","💂","🕵","👰","🤵","👸","🤴","🤶","🎅","🦸","🦹","🧙","🧝","🧛","🧟","🧞","🧜","🧚","👼","🤰","🤱","🙇","💁","🙅","🙆","🙋","🤦","🤷","🙎","🙍","💇","💆","🧖","💅","🤳","💃","🕺","👯","🕴","🚶","🏃","👫","👭","👬","💑","💏","👪","🧥","👚","👕","👖","👔","👗","👙","👘","🥼","👠","👡","👢","👞","👟","🥾","🥿","🧦","🧤","🧣","🎩","🧢","👒","🎓","⛑","👑","👝","👛","👜","💼","🎒","👓","🕶","🥽","🌂","🦰","🦱","🦳","🦲","🇿","🇾","🇽","🇼","🇻","🇺","🇹","🇸","🇷","🇶","🇵","🇴","🇳","🇲","🇱","🇰","🇯","🇮","🇭","🇬","🇫","🇪","🇩","🇨","🇧","🇦","🚗","🚕","🚙","🚌","🚎","🏎","🚓","🚑","🚒","🚐","🚚","🚛","🚜","🛴","🚲","🛵","🏍","🚨","🚔","🚍","🚘","🚖","🚡","🚠","🚟","🚃","🚋","🚞","🚝","🚄","🚅","🚈","🚂","🚆","🚇","🚊","🚉","🛫","🛬","🛩","💺","🧳","🛰","🚀","🛸","🚁","🛶","⛵","🚤","🛥","🛳","⛴","🚢","⛽","🚧","🚦","🚥","🚏","🗺","🗿","🗽","🗼","🏰","🏯","🏟","🎡","🎢","🎠","⛲","⛱","🏖","🏝","🏜","🌋","⛰","🏔","🗻","🏕","⛺","🏠","🏡","🏘","🏚","🏗","🏭","🏢","🏬","🏣","🏤","🏥","🏦","🏨","🏪","🏫","🏩","💒","🏛","⛪","🕌","🕍","🕋","⛩","🛤","🛣","🗾","🎑","🏞","🌅","🌄","🌠","🎇","🎆","🧨","🌇","🌆","🏙","🌃","🌌","🌉","🔒","🔓","🌁","🏳","🏴","🏁","🚩","🎌","🏻","🏼","🏽","🏾","🏿"]};x.extend(!0,x.trumbowyg,{langs:{en:{emoji:"Add an emoji"},da:{emoji:"Tilføj et humørikon"},de:{emoji:"Emoticon einfügen"},fr:{emoji:"Ajouter un emoji"},zh_cn:{emoji:"添加表情"},ru:{emoji:"Вставить emoji"},ja:{emoji:"絵文字の挿入"},tr:{emoji:"Emoji ekle"},ko:{emoji:"이모지 넣기"}},plugins:{emoji:{init:function(x){x.o.plugins.emoji=x.o.plugins.emoji||E;var B={dropdown:F(x)};x.addBtnDef("emoji",B)}}}})}(jQuery); \ No newline at end of file diff --git a/assets/ext/trumbowyg/plugins/emoji/ui/sass/trumbowyg.emoji.scss b/assets/ext/trumbowyg/plugins/emoji/ui/sass/trumbowyg.emoji.scss new file mode 100644 index 00000000..535b6318 --- /dev/null +++ b/assets/ext/trumbowyg/plugins/emoji/ui/sass/trumbowyg.emoji.scss @@ -0,0 +1,53 @@ +/** + * Trumbowyg v2.21.0 - A lightweight WYSIWYG editor + * Default stylesheet for Trumbowyg editor plugin + * ------------------------ + * @link http://alex-d.github.io/Trumbowyg + * @license MIT + * @author Alexandre Demode (Alex-D) + * Twitter : @AlexandreDemode + * Website : alex-d.fr + */ + +.trumbowyg-dropdown-emoji { + width: 265px; + padding: 7px 0 7px 5px; +} + +.trumbowyg-dropdown-emoji svg { + display: none !important; +} + +.trumbowyg-dropdown-emoji button { + display: block; + position: relative; + float: left; + height: 26px; + width: 26px; + padding: 0; + margin: 2px; + line-height: 24px; + text-align: center; + + &:hover, + &:focus { + &::after { + display: block; + position: absolute; + top: -5px; + left: -5px; + height: 27px; + width: 27px; + background: inherit; + box-shadow: #000 0 0 2px; + z-index: 10; + background-color: transparent; + } + } +} + +.trumbowyg .emoji { + width: 22px; + height: 22px; + display: inline-block; +} diff --git a/assets/ext/trumbowyg/plugins/emoji/ui/trumbowyg.emoji.css b/assets/ext/trumbowyg/plugins/emoji/ui/trumbowyg.emoji.css new file mode 100644 index 00000000..f7488895 --- /dev/null +++ b/assets/ext/trumbowyg/plugins/emoji/ui/trumbowyg.emoji.css @@ -0,0 +1,44 @@ +/** + * Trumbowyg v2.21.0 - A lightweight WYSIWYG editor + * Trumbowyg plugin stylesheet + * ------------------------ + * @link http://alex-d.github.io/Trumbowyg + * @license MIT + * @author Alexandre Demode (Alex-D) + * Twitter : @AlexandreDemode + * Website : alex-d.fr + */ + +.trumbowyg-dropdown-emoji { + width: 265px; + padding: 7px 0 7px 5px; } + +.trumbowyg-dropdown-emoji svg { + display: none !important; } + +.trumbowyg-dropdown-emoji button { + display: block; + position: relative; + float: left; + height: 26px; + width: 26px; + padding: 0; + margin: 2px; + line-height: 24px; + text-align: center; } + .trumbowyg-dropdown-emoji button:hover::after, .trumbowyg-dropdown-emoji button:focus::after { + display: block; + position: absolute; + top: -5px; + left: -5px; + height: 27px; + width: 27px; + background: inherit; + box-shadow: #000 0 0 2px; + z-index: 10; + background-color: transparent; } + +.trumbowyg .emoji { + width: 22px; + height: 22px; + display: inline-block; } diff --git a/assets/ext/trumbowyg/plugins/emoji/ui/trumbowyg.emoji.min.css b/assets/ext/trumbowyg/plugins/emoji/ui/trumbowyg.emoji.min.css new file mode 100644 index 00000000..da37a7ef --- /dev/null +++ b/assets/ext/trumbowyg/plugins/emoji/ui/trumbowyg.emoji.min.css @@ -0,0 +1,2 @@ +/** Trumbowyg v2.21.0 - A lightweight WYSIWYG editor - alex-d.github.io/Trumbowyg - License MIT - Author : Alexandre Demode (Alex-D) / alex-d.fr */ +.trumbowyg-dropdown-emoji{width:265px;padding:7px 0 7px 5px}.trumbowyg-dropdown-emoji svg{display:none!important}.trumbowyg-dropdown-emoji button{display:block;position:relative;float:left;height:26px;width:26px;padding:0;margin:2px;line-height:24px;text-align:center}.trumbowyg-dropdown-emoji button:focus::after,.trumbowyg-dropdown-emoji button:hover::after{display:block;position:absolute;top:-5px;left:-5px;height:27px;width:27px;background:inherit;box-shadow:#000 0 0 2px;z-index:10;background-color:transparent}.trumbowyg .emoji{width:22px;height:22px;display:inline-block} \ No newline at end of file diff --git a/assets/ext/trumbowyg/plugins/fontfamily/trumbowyg.fontfamily.js b/assets/ext/trumbowyg/plugins/fontfamily/trumbowyg.fontfamily.js new file mode 100644 index 00000000..b23f860c --- /dev/null +++ b/assets/ext/trumbowyg/plugins/fontfamily/trumbowyg.fontfamily.js @@ -0,0 +1,95 @@ +(function ($) { + 'use strict'; + + $.extend(true, $.trumbowyg, { + langs: { + // jshint camelcase:false + en: { + fontFamily: 'Font' + }, + es: { + fontFamily: 'Fuente' + }, + da: { + fontFamily: 'Skrifttype' + }, + fr: { + fontFamily: 'Police' + }, + de: { + fontFamily: 'Schriftart' + }, + nl: { + fontFamily: 'Lettertype' + }, + tr: { + fontFamily: 'Yazı Tipi' + }, + zh_tw: { + fontFamily: '字體', + }, + pt_br: { + fontFamily: 'Fonte', + }, + ko: { + fontFamily: '글꼴' + }, + } + }); + // jshint camelcase:true + + var defaultOptions = { + fontList: [ + {name: 'Arial', family: 'Arial, Helvetica, sans-serif'}, + {name: 'Arial Black', family: 'Arial Black, Gadget, sans-serif'}, + {name: 'Comic Sans', family: 'Comic Sans MS, Textile, cursive, sans-serif'}, + {name: 'Courier New', family: 'Courier New, Courier, monospace'}, + {name: 'Georgia', family: 'Georgia, serif'}, + {name: 'Impact', family: 'Impact, Charcoal, sans-serif'}, + {name: 'Lucida Console', family: 'Lucida Console, Monaco, monospace'}, + {name: 'Lucida Sans', family: 'Lucida Sans Uncide, Lucida Grande, sans-serif'}, + {name: 'Palatino', family: 'Palatino Linotype, Book Antiqua, Palatino, serif'}, + {name: 'Tahoma', family: 'Tahoma, Geneva, sans-serif'}, + {name: 'Times New Roman', family: 'Times New Roman, Times, serif'}, + {name: 'Trebuchet', family: 'Trebuchet MS, Helvetica, sans-serif'}, + {name: 'Verdana', family: 'Verdana, Geneva, sans-serif'} + ] + }; + + // Add dropdown with web safe fonts + $.extend(true, $.trumbowyg, { + plugins: { + fontfamily: { + init: function (trumbowyg) { + trumbowyg.o.plugins.fontfamily = $.extend({}, + defaultOptions, + trumbowyg.o.plugins.fontfamily || {} + ); + + trumbowyg.addBtnDef('fontfamily', { + dropdown: buildDropdown(trumbowyg), + hasIcon: false, + text: trumbowyg.lang.fontFamily + }); + } + } + } + }); + + function buildDropdown(trumbowyg) { + var dropdown = []; + + $.each(trumbowyg.o.plugins.fontfamily.fontList, function (index, font) { + trumbowyg.addBtnDef('fontfamily_' + index, { + title: '' + font.name + '', + hasIcon: false, + fn: function () { + trumbowyg.execCmd('fontName', font.family, true); + } + }); + dropdown.push('fontfamily_' + index); + }); + + return dropdown; + } +})(jQuery); diff --git a/assets/ext/trumbowyg/plugins/fontfamily/trumbowyg.fontfamily.min.js b/assets/ext/trumbowyg/plugins/fontfamily/trumbowyg.fontfamily.min.js new file mode 100644 index 00000000..1ee141f6 --- /dev/null +++ b/assets/ext/trumbowyg/plugins/fontfamily/trumbowyg.fontfamily.min.js @@ -0,0 +1 @@ +!function(a){"use strict";function n(n){var i=[];return a.each(n.o.plugins.fontfamily.fontList,function(a,e){n.addBtnDef("fontfamily_"+a,{title:''+e.name+"",hasIcon:!1,fn:function(){n.execCmd("fontName",e.family,!0)}}),i.push("fontfamily_"+a)}),i}a.extend(!0,a.trumbowyg,{langs:{en:{fontFamily:"Font"},es:{fontFamily:"Fuente"},da:{fontFamily:"Skrifttype"},fr:{fontFamily:"Police"},de:{fontFamily:"Schriftart"},nl:{fontFamily:"Lettertype"},tr:{fontFamily:"Yazı Tipi"},zh_tw:{fontFamily:"字體"},pt_br:{fontFamily:"Fonte"},ko:{fontFamily:"글꼴"}}});var i={fontList:[{name:"Arial",family:"Arial, Helvetica, sans-serif"},{name:"Arial Black",family:"Arial Black, Gadget, sans-serif"},{name:"Comic Sans",family:"Comic Sans MS, Textile, cursive, sans-serif"},{name:"Courier New",family:"Courier New, Courier, monospace"},{name:"Georgia",family:"Georgia, serif"},{name:"Impact",family:"Impact, Charcoal, sans-serif"},{name:"Lucida Console",family:"Lucida Console, Monaco, monospace"},{name:"Lucida Sans",family:"Lucida Sans Uncide, Lucida Grande, sans-serif"},{name:"Palatino",family:"Palatino Linotype, Book Antiqua, Palatino, serif"},{name:"Tahoma",family:"Tahoma, Geneva, sans-serif"},{name:"Times New Roman",family:"Times New Roman, Times, serif"},{name:"Trebuchet",family:"Trebuchet MS, Helvetica, sans-serif"},{name:"Verdana",family:"Verdana, Geneva, sans-serif"}]};a.extend(!0,a.trumbowyg,{plugins:{fontfamily:{init:function(e){e.o.plugins.fontfamily=a.extend({},i,e.o.plugins.fontfamily||{}),e.addBtnDef("fontfamily",{dropdown:n(e),hasIcon:!1,text:e.lang.fontFamily})}}}})}(jQuery); \ No newline at end of file diff --git a/assets/ext/trumbowyg/plugins/fontsize/trumbowyg.fontsize.js b/assets/ext/trumbowyg/plugins/fontsize/trumbowyg.fontsize.js new file mode 100644 index 00000000..03bcbc4c --- /dev/null +++ b/assets/ext/trumbowyg/plugins/fontsize/trumbowyg.fontsize.js @@ -0,0 +1,257 @@ +(function ($) { + 'use strict'; + + $.extend(true, $.trumbowyg, { + langs: { + // jshint camelcase:false + en: { + fontsize: 'Font size', + fontsizes: { + 'x-small': 'Extra small', + 'small': 'Small', + 'medium': 'Regular', + 'large': 'Large', + 'x-large': 'Extra large', + 'custom': 'Custom' + }, + fontCustomSize: { + title: 'Custom Font Size', + label: 'Font Size', + value: '48px' + } + }, + es: { + fontsize: 'Tamaño de Fuente', + fontsizes: { + 'x-small': 'Extra pequeña', + 'small': 'Pegueña', + 'medium': 'Regular', + 'large': 'Grande', + 'x-large': 'Extra Grande', + 'custom': 'Customizada' + }, + fontCustomSize: { + title: 'Tamaño de Fuente Customizada', + label: 'Tamaño de Fuente', + value: '48px' + } + }, + da: { + fontsize: 'Skriftstørrelse', + fontsizes: { + 'x-small': 'Ekstra lille', + 'small': 'Lille', + 'medium': 'Normal', + 'large': 'Stor', + 'x-large': 'Ekstra stor', + 'custom': 'Brugerdefineret' + } + }, + fr: { + fontsize: 'Taille de la police', + fontsizes: { + 'x-small': 'Très petit', + 'small': 'Petit', + 'medium': 'Normal', + 'large': 'Grand', + 'x-large': 'Très grand', + 'custom': 'Taille personnalisée' + }, + fontCustomSize: { + title: 'Taille de police personnalisée', + label: 'Taille de la police', + value: '48px' + } + }, + de: { + fontsize: 'Schriftgröße', + fontsizes: { + 'x-small': 'Sehr klein', + 'small': 'Klein', + 'medium': 'Normal', + 'large': 'Groß', + 'x-large': 'Sehr groß', + 'custom': 'Benutzerdefiniert' + }, + fontCustomSize: { + title: 'Benutzerdefinierte Schriftgröße', + label: 'Schriftgröße', + value: '48px' + } + }, + nl: { + fontsize: 'Lettergrootte', + fontsizes: { + 'x-small': 'Extra klein', + 'small': 'Klein', + 'medium': 'Normaal', + 'large': 'Groot', + 'x-large': 'Extra groot', + 'custom': 'Tilpasset' + } + }, + tr: { + fontsize: 'Yazı Boyutu', + fontsizes: { + 'x-small': 'Çok Küçük', + 'small': 'Küçük', + 'medium': 'Normal', + 'large': 'Büyük', + 'x-large': 'Çok Büyük', + 'custom': 'Görenek' + } + }, + zh_tw: { + fontsize: '字體大小', + fontsizes: { + 'x-small': '最小', + 'small': '小', + 'medium': '中', + 'large': '大', + 'x-large': '最大', + 'custom': '自訂大小', + }, + fontCustomSize: { + title: '自訂義字體大小', + label: '字體大小', + value: '48px' + } + }, + pt_br: { + fontsize: 'Tamanho da fonte', + fontsizes: { + 'x-small': 'Extra pequeno', + 'small': 'Pequeno', + 'regular': 'Médio', + 'large': 'Grande', + 'x-large': 'Extra grande', + 'custom': 'Personalizado' + }, + fontCustomSize: { + title: 'Tamanho de Fonte Personalizado', + label: 'Tamanho de Fonte', + value: '48px' + } + }, + it: { + fontsize: 'Dimensioni del testo', + fontsizes: { + 'x-small': 'Molto piccolo', + 'small': 'piccolo', + 'regular': 'normale', + 'large': 'grande', + 'x-large': 'Molto grande', + 'custom': 'Personalizzato' + }, + fontCustomSize: { + title: 'Dimensioni del testo personalizzato', + label: 'Dimensioni del testo', + value: '48px' + } + }, + ko: { + fontsize: '글꼴 크기', + fontsizes: { + 'x-small': '아주 작게', + 'small': '작게', + 'medium': '보통', + 'large': '크게', + 'x-large': '아주 크게', + 'custom': '사용자 지정' + }, + fontCustomSize: { + title: '사용자 지정 글꼴 크기', + label: '글꼴 크기', + value: '48px' + } + }, + } + }); + // jshint camelcase:true + + var defaultOptions = { + sizeList: [ + 'x-small', + 'small', + 'medium', + 'large', + 'x-large' + ], + allowCustomSize: true + }; + + // Add dropdown with font sizes + $.extend(true, $.trumbowyg, { + plugins: { + fontsize: { + init: function (trumbowyg) { + trumbowyg.o.plugins.fontsize = $.extend({}, + defaultOptions, + trumbowyg.o.plugins.fontsize || {} + ); + + trumbowyg.addBtnDef('fontsize', { + dropdown: buildDropdown(trumbowyg) + }); + } + } + } + }); + + function setFontSize(trumbowyg, size) { + trumbowyg.$ed.focus(); + trumbowyg.saveRange(); + var text = trumbowyg.range.startContainer.parentElement; + var selectedText = trumbowyg.getRangeText(); + if ($(text).html() === selectedText) { + $(text).css('font-size', size); + } else { + trumbowyg.range.deleteContents(); + var html = '' + selectedText + ''; + var node = $(html)[0]; + trumbowyg.range.insertNode(node); + } + trumbowyg.restoreRange(); + } + + function buildDropdown(trumbowyg) { + var dropdown = []; + + $.each(trumbowyg.o.plugins.fontsize.sizeList, function (index, size) { + trumbowyg.addBtnDef('fontsize_' + size, { + text: '' + (trumbowyg.lang.fontsizes[size] || size) + '', + hasIcon: false, + fn: function () { + setFontSize(trumbowyg, size); + } + }); + dropdown.push('fontsize_' + size); + }); + + if (trumbowyg.o.plugins.fontsize.allowCustomSize) { + var customSizeButtonName = 'fontsize_custom'; + var customSizeBtnDef = { + fn: function () { + trumbowyg.openModalInsert(trumbowyg.lang.fontCustomSize.title, + { + size: { + label: trumbowyg.lang.fontCustomSize.label, + value: trumbowyg.lang.fontCustomSize.value + } + }, + function (form) { + setFontSize(trumbowyg, form.size); + return true; + } + ); + }, + text: '' + trumbowyg.lang.fontsizes.custom + '', + hasIcon: false + }; + trumbowyg.addBtnDef(customSizeButtonName, customSizeBtnDef); + dropdown.push(customSizeButtonName); + } + + return dropdown; + } +})(jQuery); diff --git a/assets/ext/trumbowyg/plugins/fontsize/trumbowyg.fontsize.min.js b/assets/ext/trumbowyg/plugins/fontsize/trumbowyg.fontsize.min.js new file mode 100644 index 00000000..fee6c0a0 --- /dev/null +++ b/assets/ext/trumbowyg/plugins/fontsize/trumbowyg.fontsize.min.js @@ -0,0 +1 @@ +!function(e){"use strict";function t(t,l){t.$ed.focus(),t.saveRange();var a=t.range.startContainer.parentElement,o=t.getRangeText();if(e(a).html()===o)e(a).css("font-size",l);else{t.range.deleteContents();var s=''+o+"",n=e(s)[0];t.range.insertNode(n)}t.restoreRange()}function l(l){var a=[];if(e.each(l.o.plugins.fontsize.sizeList,function(e,o){l.addBtnDef("fontsize_"+o,{text:''+(l.lang.fontsizes[o]||o)+"",hasIcon:!1,fn:function(){t(l,o)}}),a.push("fontsize_"+o)}),l.o.plugins.fontsize.allowCustomSize){var o="fontsize_custom",s={fn:function(){l.openModalInsert(l.lang.fontCustomSize.title,{size:{label:l.lang.fontCustomSize.label,value:l.lang.fontCustomSize.value}},function(e){return t(l,e.size),!0})},text:''+l.lang.fontsizes.custom+"",hasIcon:!1};l.addBtnDef(o,s),a.push(o)}return a}e.extend(!0,e.trumbowyg,{langs:{en:{fontsize:"Font size",fontsizes:{"x-small":"Extra small",small:"Small",medium:"Regular",large:"Large","x-large":"Extra large",custom:"Custom"},fontCustomSize:{title:"Custom Font Size",label:"Font Size",value:"48px"}},es:{fontsize:"Tamaño de Fuente",fontsizes:{"x-small":"Extra pequeña",small:"Pegueña",medium:"Regular",large:"Grande","x-large":"Extra Grande",custom:"Customizada"},fontCustomSize:{title:"Tamaño de Fuente Customizada",label:"Tamaño de Fuente",value:"48px"}},da:{fontsize:"Skriftstørrelse",fontsizes:{"x-small":"Ekstra lille",small:"Lille",medium:"Normal",large:"Stor","x-large":"Ekstra stor",custom:"Brugerdefineret"}},fr:{fontsize:"Taille de la police",fontsizes:{"x-small":"Très petit",small:"Petit",medium:"Normal",large:"Grand","x-large":"Très grand",custom:"Taille personnalisée"},fontCustomSize:{title:"Taille de police personnalisée",label:"Taille de la police",value:"48px"}},de:{fontsize:"Schriftgröße",fontsizes:{"x-small":"Sehr klein",small:"Klein",medium:"Normal",large:"Groß","x-large":"Sehr groß",custom:"Benutzerdefiniert"},fontCustomSize:{title:"Benutzerdefinierte Schriftgröße",label:"Schriftgröße",value:"48px"}},nl:{fontsize:"Lettergrootte",fontsizes:{"x-small":"Extra klein",small:"Klein",medium:"Normaal",large:"Groot","x-large":"Extra groot",custom:"Tilpasset"}},tr:{fontsize:"Yazı Boyutu",fontsizes:{"x-small":"Çok Küçük",small:"Küçük",medium:"Normal",large:"Büyük","x-large":"Çok Büyük",custom:"Görenek"}},zh_tw:{fontsize:"字體大小",fontsizes:{"x-small":"最小",small:"小",medium:"中",large:"大","x-large":"最大",custom:"自訂大小"},fontCustomSize:{title:"自訂義字體大小",label:"字體大小",value:"48px"}},pt_br:{fontsize:"Tamanho da fonte",fontsizes:{"x-small":"Extra pequeno",small:"Pequeno",regular:"Médio",large:"Grande","x-large":"Extra grande",custom:"Personalizado"},fontCustomSize:{title:"Tamanho de Fonte Personalizado",label:"Tamanho de Fonte",value:"48px"}},it:{fontsize:"Dimensioni del testo",fontsizes:{"x-small":"Molto piccolo",small:"piccolo",regular:"normale",large:"grande","x-large":"Molto grande",custom:"Personalizzato"},fontCustomSize:{title:"Dimensioni del testo personalizzato",label:"Dimensioni del testo",value:"48px"}},ko:{fontsize:"글꼴 크기",fontsizes:{"x-small":"아주 작게",small:"작게",medium:"보통",large:"크게","x-large":"아주 크게",custom:"사용자 지정"},fontCustomSize:{title:"사용자 지정 글꼴 크기",label:"글꼴 크기",value:"48px"}}}});var a={sizeList:["x-small","small","medium","large","x-large"],allowCustomSize:!0};e.extend(!0,e.trumbowyg,{plugins:{fontsize:{init:function(t){t.o.plugins.fontsize=e.extend({},a,t.o.plugins.fontsize||{}),t.addBtnDef("fontsize",{dropdown:l(t)})}}}})}(jQuery); \ No newline at end of file diff --git a/assets/ext/trumbowyg/plugins/giphy/trumbowyg.giphy.js b/assets/ext/trumbowyg/plugins/giphy/trumbowyg.giphy.js new file mode 100644 index 00000000..4c3dc75e --- /dev/null +++ b/assets/ext/trumbowyg/plugins/giphy/trumbowyg.giphy.js @@ -0,0 +1,182 @@ +(function ($) { + 'use strict'; + + $.extend(true, $.trumbowyg, { + langs: { + // jshint camelcase:false + en: { + giphy: 'Insert GIF', + }, + fr: { + giphy: 'Insérer un GIF', + }, + // jshint camelcase:true + } + }); + + var giphyLogo = ''; + + var CANCEL_EVENT = 'tbwcancel'; + + // Throttle helper + function trumbowygThrottle(callback, delay) { + var last; + var timer; + + return function () { + var context = this; + var now = +new Date(); + var args = arguments; + + if (last && now < last + delay) { + clearTimeout(timer); + timer = setTimeout(function () { + last = now; + callback.apply(context, args); + }, delay); + } else { + last = now; + callback.apply(context, args); + } + }; + } + + // Fills modal with response gifs + function renderGifs(response, $giphyModal, trumbowyg, mustEmpty) { + var width = ($giphyModal.width() - 20) / 3; + + var html = response.data + .filter(function (gifData) { + return gifData.images.downsized.url !== ''; + }) + .map(function (gifData) { + var image = gifData.images.downsized, + imageRatio = image.height / image.width; + + return '
      '; + }) + .join('') + ; + + if (mustEmpty === true) { + if (html.length === 0) { + if ($('.' + trumbowyg.o.prefix + 'giphy-no-result', $giphyModal).length > 0) { + return; + } + + html = ''; + } + + $giphyModal.empty(); + } + $giphyModal.append(html); + $('img', $giphyModal).on('click', function () { + trumbowyg.restoreRange(); + trumbowyg.execCmd('insertImage', $(this).attr('src'), false, true); + $('img', $giphyModal).off(); + trumbowyg.closeModal(); + }); + } + + var defaultOptions = { + rating: 'g', + apiKey: null, + throttleDelay: 300, + noResultGifUrl: 'https://media.giphy.com/media/2Faz9FbRzmwxY0pZS/giphy.gif' + }; + + // Add dropdown with font sizes + $.extend(true, $.trumbowyg, { + plugins: { + giphy: { + init: function (trumbowyg) { + trumbowyg.o.plugins.giphy = $.extend({}, + defaultOptions, + trumbowyg.o.plugins.giphy || {} + ); + + trumbowyg.addBtnDef('giphy', { + fn: function() { + if (trumbowyg.o.plugins.giphy.apiKey === null) { + throw new Error('You must set a Giphy API Key'); + } + + var BASE_URL = 'https://api.giphy.com/v1/gifs/search?api_key=' + trumbowyg.o.plugins.giphy.apiKey + '&rating=' + trumbowyg.o.plugins.giphy.rating, + DEFAULT_URL = BASE_URL.replace('/search', '/trending'); + var previousAjaxCall = {abort: function () {}}; + var prefix = trumbowyg.o.prefix; + + // Create and open the modal + var searchInput = '', + closeButton = '', + poweredByGiphy = '
      Powered by' + giphyLogo + '
      ', + giphyModalHtml = searchInput + closeButton + poweredByGiphy + '
      '; + + trumbowyg + .openModal(null, giphyModalHtml, false) + .one(CANCEL_EVENT, function () { + try { + previousAjaxCall.abort(); + } catch (e) {} + + trumbowyg.closeModal(); + }); + + var $giphyInput = $('.' + prefix + 'giphy-search'), + $giphyClose = $('.' + prefix + 'giphy-close'), + $giphyModal = $('.' + prefix + 'giphy-modal'); + + var ajaxError = function () { + if (!navigator.onLine && !$('.' + prefix + 'giphy-offline', $giphyModal).length) { + $giphyModal.empty(); + $giphyModal.append('

      You are offline

      '); + } + }; + + // Load trending gifs as default + $.ajax({ + url: DEFAULT_URL, + dataType: 'json', + + success: function(response) { + renderGifs(response, $giphyModal, trumbowyg, true); + }, + error: ajaxError + }); + + var searchGifsOnInput = function () { + var query = $giphyInput.val(); + + if (query.length === 0) { + return; + } + + try { + previousAjaxCall.abort(); + } catch (e) {} + + previousAjaxCall = $.ajax({ + url: BASE_URL + '&q=' + encodeURIComponent(query), + dataType: 'json', + + success: function(response) { + renderGifs(response, $giphyModal, trumbowyg, true); + }, + error: ajaxError + }); + }; + var throttledInputRequest = trumbowygThrottle(searchGifsOnInput, trumbowyg.o.plugins.giphy.throttleDelay); + + $giphyInput.on('input', throttledInputRequest); + $giphyInput.focus(); + + $giphyClose.one('click', function() { + $giphyModal.trigger(CANCEL_EVENT); + }); + }, + }); + } + } + } + }); +})(jQuery); diff --git a/assets/ext/trumbowyg/plugins/giphy/trumbowyg.giphy.min.js b/assets/ext/trumbowyg/plugins/giphy/trumbowyg.giphy.min.js new file mode 100644 index 00000000..b0f140c4 --- /dev/null +++ b/assets/ext/trumbowyg/plugins/giphy/trumbowyg.giphy.min.js @@ -0,0 +1 @@ +!function(i){"use strict";function e(i,e){var n,t;return function(){var o=this,l=+new Date,c=arguments;n&&l
      '}).join("");if(o===!0){if(0===c.length){if(i("."+t.o.prefix+"giphy-no-result",n).length>0)return;c=''}n.empty()}n.append(c),i("img",n).on("click",function(){t.restoreRange(),t.execCmd("insertImage",i(this).attr("src"),!1,!0),i("img",n).off(),t.closeModal()})}i.extend(!0,i.trumbowyg,{langs:{en:{giphy:"Insert GIF"},fr:{giphy:"Insérer un GIF"}}});var t='',o="tbwcancel",l={rating:"g",apiKey:null,throttleDelay:300,noResultGifUrl:"https://media.giphy.com/media/2Faz9FbRzmwxY0pZS/giphy.gif"};i.extend(!0,i.trumbowyg,{plugins:{giphy:{init:function(c){c.o.plugins.giphy=i.extend({},l,c.o.plugins.giphy||{}),c.addBtnDef("giphy",{fn:function(){if(null===c.o.plugins.giphy.apiKey)throw new Error("You must set a Giphy API Key");var l="https://api.giphy.com/v1/gifs/search?api_key="+c.o.plugins.giphy.apiKey+"&rating="+c.o.plugins.giphy.rating,a=l.replace("/search","/trending"),r={abort:function(){}},s=c.o.prefix,p='',g='',u='
      Powered by'+t+"
      ",h=p+g+u+'
      ';c.openModal(null,h,!1).one(o,function(){try{r.abort()}catch(i){}c.closeModal()});var d=i("."+s+"giphy-search"),f=i("."+s+"giphy-close"),y=i("."+s+"giphy-modal"),v=function(){navigator.onLine||i("."+s+"giphy-offline",y).length||(y.empty(),y.append('

      You are offline

      '))};i.ajax({url:a,dataType:"json",success:function(i){n(i,y,c,!0)},error:v});var m=function(){var e=d.val();if(0!==e.length){try{r.abort()}catch(t){}r=i.ajax({url:l+"&q="+encodeURIComponent(e),dataType:"json",success:function(i){n(i,y,c,!0)},error:v})}},w=e(m,c.o.plugins.giphy.throttleDelay);d.on("input",w),d.focus(),f.one("click",function(){y.trigger(o)})}})}}}})}(jQuery); \ No newline at end of file diff --git a/assets/ext/trumbowyg/plugins/giphy/ui/sass/trumbowyg.giphy.scss b/assets/ext/trumbowyg/plugins/giphy/ui/sass/trumbowyg.giphy.scss new file mode 100644 index 00000000..ec5dc6cb --- /dev/null +++ b/assets/ext/trumbowyg/plugins/giphy/ui/sass/trumbowyg.giphy.scss @@ -0,0 +1,111 @@ +/** + * Trumbowyg v2.21.0 - A lightweight WYSIWYG editor + * Default stylesheet for Trumbowyg editor plugin + * ------------------------ + * @link http://alex-d.github.io/Trumbowyg + * @license MIT + * @author Alexandre Demode (Alex-D) + * Twitter : @AlexandreDemode + * Website : alex-d.fr + */ + +.trumbowyg-giphy-button svg { + transform: scale(1.22); +} + +.trumbowyg-giphy-search { + display: block; + width: 80%; + margin: 5%; + padding-left: 10px; + padding-right: 150px; +} + +.trumbowyg-giphy-close { + position: absolute; + top: calc(5% + 8px); + right: calc(5% - 2px); + width: 30px; + height: 30px; + background: none; + border: 1px solid transparent; + + &:hover, + &:focus { + outline: none; + background: #ecf0f1; + } + &:focus { + border-color: rgba(0, 0, 0, 0.3); + } +} + +.trumbowyg-powered-by-giphy { + position: absolute; + top: calc(5% + 12px); + right: calc(15% + 10px); + pointer-events: none; + user-select: none; + + span { + text-transform: uppercase; + font-weight: bold; + font-size: 10px; + opacity: 0.6; + } + + svg { + width: 66px; + height: 15px; + vertical-align: bottom; + margin-left: 6px; + opacity: 0.45; + } +} + +.trumbowyg-giphy-modal-scroll { + overflow: auto; + overflow-x: hidden; + height: 240px; +} + +.trumbowyg-giphy-modal { + padding: 0 5%; + columns: 3; + column-gap: 10px; + + .trumbowyg-giphy-no-result { + width: 250%; + margin: 13% 0 0 29%; + } + + .trumbowyg-giphy-offline { + font-size: 18px; + width: 305%; + height: 600px; + margin-top: 95px; + text-align: center; + } +} + +.trumbowyg-giphy-modal .img-container { + width: 100%; + margin-bottom: 10px; + background-color: #ecf0f1; + + img { + width: 100%; + cursor: pointer; + opacity: 0; + transition: opacity 150ms; + + &:hover, + &:focus { + border: #2ecc71 solid 3px; + } + } + + img.tbw-loaded { + opacity: 1; + } +} diff --git a/assets/ext/trumbowyg/plugins/giphy/ui/trumbowyg.giphy.css b/assets/ext/trumbowyg/plugins/giphy/ui/trumbowyg.giphy.css new file mode 100644 index 00000000..5daaf9e7 --- /dev/null +++ b/assets/ext/trumbowyg/plugins/giphy/ui/trumbowyg.giphy.css @@ -0,0 +1,90 @@ +/** + * Trumbowyg v2.21.0 - A lightweight WYSIWYG editor + * Trumbowyg plugin stylesheet + * ------------------------ + * @link http://alex-d.github.io/Trumbowyg + * @license MIT + * @author Alexandre Demode (Alex-D) + * Twitter : @AlexandreDemode + * Website : alex-d.fr + */ + +.trumbowyg-giphy-button svg { + transform: scale(1.22); } + +.trumbowyg-giphy-search { + display: block; + width: 80%; + margin: 5%; + padding-left: 10px; + padding-right: 150px; } + +.trumbowyg-giphy-close { + position: absolute; + top: calc(5% + 8px); + right: calc(5% - 2px); + width: 30px; + height: 30px; + background: none; + border: 1px solid transparent; } + .trumbowyg-giphy-close:hover, .trumbowyg-giphy-close:focus { + outline: none; + background: #ecf0f1; } + .trumbowyg-giphy-close:focus { + border-color: rgba(0, 0, 0, 0.3); } + +.trumbowyg-powered-by-giphy { + position: absolute; + top: calc(5% + 12px); + right: calc(15% + 10px); + pointer-events: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } + .trumbowyg-powered-by-giphy span { + text-transform: uppercase; + font-weight: bold; + font-size: 10px; + opacity: 0.6; } + .trumbowyg-powered-by-giphy svg { + width: 66px; + height: 15px; + vertical-align: bottom; + margin-left: 6px; + opacity: 0.45; } + +.trumbowyg-giphy-modal-scroll { + overflow: auto; + overflow-x: hidden; + height: 240px; } + +.trumbowyg-giphy-modal { + padding: 0 5%; + -moz-columns: 3; + columns: 3; + -moz-column-gap: 10px; + column-gap: 10px; } + .trumbowyg-giphy-modal .trumbowyg-giphy-no-result { + width: 250%; + margin: 13% 0 0 29%; } + .trumbowyg-giphy-modal .trumbowyg-giphy-offline { + font-size: 18px; + width: 305%; + height: 600px; + margin-top: 95px; + text-align: center; } + +.trumbowyg-giphy-modal .img-container { + width: 100%; + margin-bottom: 10px; + background-color: #ecf0f1; } + .trumbowyg-giphy-modal .img-container img { + width: 100%; + cursor: pointer; + opacity: 0; + transition: opacity 150ms; } + .trumbowyg-giphy-modal .img-container img:hover, .trumbowyg-giphy-modal .img-container img:focus { + border: #2ecc71 solid 3px; } + .trumbowyg-giphy-modal .img-container img.tbw-loaded { + opacity: 1; } diff --git a/assets/ext/trumbowyg/plugins/giphy/ui/trumbowyg.giphy.min.css b/assets/ext/trumbowyg/plugins/giphy/ui/trumbowyg.giphy.min.css new file mode 100644 index 00000000..b2bdacc5 --- /dev/null +++ b/assets/ext/trumbowyg/plugins/giphy/ui/trumbowyg.giphy.min.css @@ -0,0 +1,2 @@ +/** Trumbowyg v2.21.0 - A lightweight WYSIWYG editor - alex-d.github.io/Trumbowyg - License MIT - Author : Alexandre Demode (Alex-D) / alex-d.fr */ +.trumbowyg-giphy-button svg{transform:scale(1.22)}.trumbowyg-giphy-search{display:block;width:80%;margin:5%;padding-left:10px;padding-right:150px}.trumbowyg-giphy-close{position:absolute;top:calc(5% + 8px);right:calc(5% - 2px);width:30px;height:30px;background:0 0;border:1px solid transparent}.trumbowyg-giphy-close:focus,.trumbowyg-giphy-close:hover{outline:0;background:#ecf0f1}.trumbowyg-giphy-close:focus{border-color:rgba(0,0,0,.3)}.trumbowyg-powered-by-giphy{position:absolute;top:calc(5% + 12px);right:calc(15% + 10px);pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.trumbowyg-powered-by-giphy span{text-transform:uppercase;font-weight:700;font-size:10px;opacity:.6}.trumbowyg-powered-by-giphy svg{width:66px;height:15px;vertical-align:bottom;margin-left:6px;opacity:.45}.trumbowyg-giphy-modal-scroll{overflow:auto;overflow-x:hidden;height:240px}.trumbowyg-giphy-modal{padding:0 5%;-moz-columns:3;columns:3;-moz-column-gap:10px;column-gap:10px}.trumbowyg-giphy-modal .trumbowyg-giphy-no-result{width:250%;margin:13% 0 0 29%}.trumbowyg-giphy-modal .trumbowyg-giphy-offline{font-size:18px;width:305%;height:600px;margin-top:95px;text-align:center}.trumbowyg-giphy-modal .img-container{width:100%;margin-bottom:10px;background-color:#ecf0f1}.trumbowyg-giphy-modal .img-container img{width:100%;cursor:pointer;opacity:0;transition:opacity 150ms}.trumbowyg-giphy-modal .img-container img:focus,.trumbowyg-giphy-modal .img-container img:hover{border:3px solid #2ecc71}.trumbowyg-giphy-modal .img-container img.tbw-loaded{opacity:1} \ No newline at end of file diff --git a/assets/ext/trumbowyg/plugins/highlight/trumbowyg.highlight.js b/assets/ext/trumbowyg/plugins/highlight/trumbowyg.highlight.js new file mode 100644 index 00000000..1ca737ca --- /dev/null +++ b/assets/ext/trumbowyg/plugins/highlight/trumbowyg.highlight.js @@ -0,0 +1,90 @@ +/* globals Prism */ +(function ($, Prism) { + 'use strict'; + + // My plugin default options + var defaultOptions = {}; + + function highlightIt(text, language) { + return [ + '
      ',
      +            '' + Prism.highlight(text, Prism.languages[language]) + '',
      +            '
      ', + ].join(''); + } + + // If my plugin is a button + function buildButtonDef(trumbowyg) { + return { + fn: function () { + var $modal = trumbowyg.openModal('Code', [ + '
      ', + ' ', + '
      ', + '
      ', + ' ', + '
      ', + ].join('\n')), + $language = $modal.find('.language'), + $code = $modal.find('.code'); + + // Listen clicks on modal box buttons + $modal.on('tbwconfirm', function () { + trumbowyg.restoreRange(); + trumbowyg.execCmd('insertHTML', highlightIt($code.val(), $language.val())); + trumbowyg.execCmd('insertHTML', '


      '); + + trumbowyg.closeModal(); + }); + + $modal.on('tbwcancel', function () { + trumbowyg.closeModal(); + }); + } + }; + } + + $.extend(true, $.trumbowyg, { + // Add some translations + langs: { + // jshint camelcase:false + en: { + highlight: 'Code syntax highlight' + }, + pt_br: { + highlight: 'Realçar sintaxe de código' + }, + ko: { + highlight: '코드 문법 하이라이트' + }, + // jshint camelcase:true + }, + // Add our plugin to Trumbowyg registered plugins + plugins: { + highlight: { + init: function (trumbowyg) { + // Fill current Trumbowyg instance with my plugin default options + trumbowyg.o.plugins.highlight = $.extend(true, {}, + defaultOptions, + trumbowyg.o.plugins.highlight || {} + ); + + // If my plugin is a button + trumbowyg.addBtnDef('highlight', buildButtonDef(trumbowyg)); + } + } + } + }); +})(jQuery, Prism); diff --git a/assets/ext/trumbowyg/plugins/highlight/trumbowyg.highlight.min.js b/assets/ext/trumbowyg/plugins/highlight/trumbowyg.highlight.min.js new file mode 100644 index 00000000..a313a14e --- /dev/null +++ b/assets/ext/trumbowyg/plugins/highlight/trumbowyg.highlight.min.js @@ -0,0 +1 @@ +!function(i,n){"use strict";function e(i,e){return['
      ',''+n.highlight(i,n.languages[e])+"","
      "].join("")}function o(i){return{fn:function(){var o=i.openModal("Code",['
      ',' ","
      ",'
      ',' ',"
      "].join("\n")),t=o.find(".language"),g=o.find(".code");o.on("tbwconfirm",function(){i.restoreRange(),i.execCmd("insertHTML",e(g.val(),t.val())),i.execCmd("insertHTML","


      "),i.closeModal()}),o.on("tbwcancel",function(){i.closeModal()})}}}var t={};i.extend(!0,i.trumbowyg,{langs:{en:{highlight:"Code syntax highlight"},pt_br:{highlight:"Realçar sintaxe de código"},ko:{highlight:"코드 문법 하이라이트"}},plugins:{highlight:{init:function(n){n.o.plugins.highlight=i.extend(!0,{},t,n.o.plugins.highlight||{}),n.addBtnDef("highlight",o(n))}}}})}(jQuery,Prism); \ No newline at end of file diff --git a/assets/ext/trumbowyg/plugins/highlight/ui/sass/trumbowyg.highlight.scss b/assets/ext/trumbowyg/plugins/highlight/ui/sass/trumbowyg.highlight.scss new file mode 100644 index 00000000..80e8c2b6 --- /dev/null +++ b/assets/ext/trumbowyg/plugins/highlight/ui/sass/trumbowyg.highlight.scss @@ -0,0 +1,25 @@ +/** + * Trumbowyg v2.21.0 - A lightweight WYSIWYG editor + * Default stylesheet for Trumbowyg editor plugin + * ------------------------ + * @link http://alex-d.github.io/Trumbowyg + * @license MIT + * @author Alexandre Demode (Alex-D) + * Twitter : @AlexandreDemode + * Website : alex-d.fr + */ + +.trumbowyg-highlight-form-group { + margin: 15px 10px; + + .trumbowyg-highlight-form-control { + width: 100%; + border: 1px solid #DEDEDE; + font-size: 14px; + padding: 7px; + + &.code { + height: 200px; + } + } +} diff --git a/assets/ext/trumbowyg/plugins/highlight/ui/trumbowyg.highlight.css b/assets/ext/trumbowyg/plugins/highlight/ui/trumbowyg.highlight.css new file mode 100644 index 00000000..e3abedfa --- /dev/null +++ b/assets/ext/trumbowyg/plugins/highlight/ui/trumbowyg.highlight.css @@ -0,0 +1,20 @@ +/** + * Trumbowyg v2.21.0 - A lightweight WYSIWYG editor + * Trumbowyg plugin stylesheet + * ------------------------ + * @link http://alex-d.github.io/Trumbowyg + * @license MIT + * @author Alexandre Demode (Alex-D) + * Twitter : @AlexandreDemode + * Website : alex-d.fr + */ + +.trumbowyg-highlight-form-group { + margin: 15px 10px; } + .trumbowyg-highlight-form-group .trumbowyg-highlight-form-control { + width: 100%; + border: 1px solid #DEDEDE; + font-size: 14px; + padding: 7px; } + .trumbowyg-highlight-form-group .trumbowyg-highlight-form-control.code { + height: 200px; } diff --git a/assets/ext/trumbowyg/plugins/highlight/ui/trumbowyg.highlight.min.css b/assets/ext/trumbowyg/plugins/highlight/ui/trumbowyg.highlight.min.css new file mode 100644 index 00000000..358a44db --- /dev/null +++ b/assets/ext/trumbowyg/plugins/highlight/ui/trumbowyg.highlight.min.css @@ -0,0 +1,2 @@ +/** Trumbowyg v2.21.0 - A lightweight WYSIWYG editor - alex-d.github.io/Trumbowyg - License MIT - Author : Alexandre Demode (Alex-D) / alex-d.fr */ +.trumbowyg-highlight-form-group{margin:15px 10px}.trumbowyg-highlight-form-group .trumbowyg-highlight-form-control{width:100%;border:1px solid #DEDEDE;font-size:14px;padding:7px}.trumbowyg-highlight-form-group .trumbowyg-highlight-form-control.code{height:200px} \ No newline at end of file diff --git a/assets/ext/trumbowyg/plugins/history/trumbowyg.history.js b/assets/ext/trumbowyg/plugins/history/trumbowyg.history.js new file mode 100644 index 00000000..a6676993 --- /dev/null +++ b/assets/ext/trumbowyg/plugins/history/trumbowyg.history.js @@ -0,0 +1,216 @@ +/*/* =========================================================== + * trumbowyg.history.js v1.0 + * history plugin for Trumbowyg + * http://alex-d.github.com/Trumbowyg + * =========================================================== + * Author : Sven Dunemann [dunemann@forelabs.eu] + */ + +(function ($) { + 'use strict'; + $.extend(true, $.trumbowyg, { + langs: { + // jshint camelcase:false + de: { + history: { + redo: 'Wiederholen', + undo: 'Rückgängig' + } + }, + en: { + history: { + redo: 'Redo', + undo: 'Undo' + } + }, + da: { + history: { + redo: 'Annuller fortryd', + undo: 'Fortryd' + } + }, + fr: { + history: { + redo: 'Annuler', + undo: 'Rétablir' + } + }, + zh_tw: { + history: { + redo: '重做', + undo: '復原' + } + }, + pt_br: { + history: { + redo: 'Refazer', + undo: 'Desfazer' + } + }, + ko: { + history: { + redo: '다시 실행', + undo: '되돌리기' + } + }, + // jshint camelcase:true + }, + plugins: { + history: { + init: function (t) { + t.o.plugins.history = $.extend(true, { + _stack: [], + _index: -1, + _focusEl: undefined + }, t.o.plugins.history || {}); + + var btnBuildDefRedo = { + title: t.lang.history.redo, + ico: 'redo', + key: 'Y', + fn: function () { + if (t.o.plugins.history._index < t.o.plugins.history._stack.length - 1) { + t.o.plugins.history._index += 1; + var index = t.o.plugins.history._index; + var newState = t.o.plugins.history._stack[index]; + + t.execCmd('html', newState); + // because of some semantic optimisations we have to save the state back + // to history + t.o.plugins.history._stack[index] = t.$ed.html(); + + carretToEnd(); + toggleButtonStates(); + } + } + }; + + var btnBuildDefUndo = { + title: t.lang.history.undo, + ico: 'undo', + key: 'Z', + fn: function () { + if (t.o.plugins.history._index > 0) { + t.o.plugins.history._index -= 1; + var index = t.o.plugins.history._index, + newState = t.o.plugins.history._stack[index]; + + t.execCmd('html', newState); + // because of some semantic optimisations we have to save the state back + // to history + t.o.plugins.history._stack[index] = t.$ed.html(); + + carretToEnd(); + toggleButtonStates(); + } + } + }; + + var pushToHistory = function () { + var index = t.o.plugins.history._index, + stack = t.o.plugins.history._stack, + latestState = stack.slice(-1)[0] || '

      ', + prevState = stack[index], + newState = t.$ed.html(), + focusEl = t.doc.getSelection().focusNode, + focusElText = '', + latestStateTagsList, + newStateTagsList, + prevFocusEl = t.o.plugins.history._focusEl; + + latestStateTagsList = $('
      ' + latestState + '
      ').find('*').map(function () { + return this.localName; + }); + newStateTagsList = $('
      ' + newState + '
      ').find('*').map(function () { + return this.localName; + }); + if (focusEl) { + t.o.plugins.history._focusEl = focusEl; + focusElText = focusEl.outerHTML || focusEl.textContent; + } + + if (newState !== prevState) { + // a new stack entry is defined when current insert ends on a whitespace character + // or count of node elements has been changed + // or focused element differs from previous one + if (focusElText.slice(-1).match(/\s/) || + !arraysAreIdentical(latestStateTagsList, newStateTagsList) || + t.o.plugins.history._index <= 0 || focusEl !== prevFocusEl) + { + t.o.plugins.history._index += 1; + // remove newer entries in history when something new was added + // because timeline was changes with interaction + t.o.plugins.history._stack = stack.slice( + 0, t.o.plugins.history._index + ); + // now add new state to modified history + t.o.plugins.history._stack.push(newState); + } else { + // modify last stack entry + t.o.plugins.history._stack[index] = newState; + } + + toggleButtonStates(); + } + }; + + var toggleButtonStates = function () { + var index = t.o.plugins.history._index, + stackSize = t.o.plugins.history._stack.length, + undoState = (index > 0), + redoState = (stackSize !== 0 && index !== stackSize - 1); + + toggleButtonState('historyUndo', undoState); + toggleButtonState('historyRedo', redoState); + }; + + var toggleButtonState = function (btn, enable) { + var button = t.$box.find('.trumbowyg-' + btn + '-button'); + + if (enable) { + button.removeClass('trumbowyg-disable'); + } else if (!button.hasClass('trumbowyg-disable')) { + button.addClass('trumbowyg-disable'); + } + }; + + var arraysAreIdentical = function (a, b) { + if (a === b) { + return true; + } + if (a == null || b == null) { + return false; + } + if (a.length !== b.length) { + return false; + } + + for (var i = 0; i < a.length; i += 1) { + if (a[i] !== b[i]) { + return false; + } + } + return true; + }; + + var carretToEnd = function () { + var node = t.doc.getSelection().focusNode, + range = t.doc.createRange(); + + if (node.childNodes.length > 0) { + range.setStartAfter(node.childNodes[node.childNodes.length - 1]); + range.setEndAfter(node.childNodes[node.childNodes.length - 1]); + t.doc.getSelection().removeAllRanges(); + t.doc.getSelection().addRange(range); + } + }; + + t.$c.on('tbwinit tbwchange', pushToHistory); + + t.addBtnDef('historyRedo', btnBuildDefRedo); + t.addBtnDef('historyUndo', btnBuildDefUndo); + } + } + } + }); +})(jQuery); diff --git a/assets/ext/trumbowyg/plugins/history/trumbowyg.history.min.js b/assets/ext/trumbowyg/plugins/history/trumbowyg.history.min.js new file mode 100644 index 00000000..8ff328a2 --- /dev/null +++ b/assets/ext/trumbowyg/plugins/history/trumbowyg.history.min.js @@ -0,0 +1 @@ +!function(o){"use strict";o.extend(!0,o.trumbowyg,{langs:{de:{history:{redo:"Wiederholen",undo:"Rückgängig"}},en:{history:{redo:"Redo",undo:"Undo"}},da:{history:{redo:"Annuller fortryd",undo:"Fortryd"}},fr:{history:{redo:"Annuler",undo:"Rétablir"}},zh_tw:{history:{redo:"重做",undo:"復原"}},pt_br:{history:{redo:"Refazer",undo:"Desfazer"}},ko:{history:{redo:"다시 실행",undo:"되돌리기"}}},plugins:{history:{init:function(i){i.o.plugins.history=o.extend(!0,{_stack:[],_index:-1,_focusEl:void 0},i.o.plugins.history||{});var t={title:i.lang.history.redo,ico:"redo",key:"Y",fn:function(){if(i.o.plugins.history._index0){i.o.plugins.history._index-=1;var o=i.o.plugins.history._index,t=i.o.plugins.history._stack[o];i.execCmd("html",t),i.o.plugins.history._stack[o]=i.$ed.html(),l(),s()}}},e=function(){var t,n,e=i.o.plugins.history._index,r=i.o.plugins.history._stack,l=r.slice(-1)[0]||"

      ",u=r[e],h=i.$ed.html(),c=i.doc.getSelection().focusNode,g="",a=i.o.plugins.history._focusEl;t=o("
      "+l+"
      ").find("*").map(function(){return this.localName}),n=o("
      "+h+"
      ").find("*").map(function(){return this.localName}),c&&(i.o.plugins.history._focusEl=c,g=c.outerHTML||c.textContent),h!==u&&(g.slice(-1).match(/\s/)||!d(t,n)||i.o.plugins.history._index<=0||c!==a?(i.o.plugins.history._index+=1,i.o.plugins.history._stack=r.slice(0,i.o.plugins.history._index),i.o.plugins.history._stack.push(h)):i.o.plugins.history._stack[e]=h,s())},s=function(){var o=i.o.plugins.history._index,t=i.o.plugins.history._stack.length,n=o>0,e=0!==t&&o!==t-1;r("historyUndo",n),r("historyRedo",e)},r=function(o,t){var n=i.$box.find(".trumbowyg-"+o+"-button");t?n.removeClass("trumbowyg-disable"):n.hasClass("trumbowyg-disable")||n.addClass("trumbowyg-disable")},d=function(o,i){if(o===i)return!0;if(null==o||null==i)return!1;if(o.length!==i.length)return!1;for(var t=0;t0&&(t.setStartAfter(o.childNodes[o.childNodes.length-1]),t.setEndAfter(o.childNodes[o.childNodes.length-1]),i.doc.getSelection().removeAllRanges(),i.doc.getSelection().addRange(t))};i.$c.on("tbwinit tbwchange",e),i.addBtnDef("historyRedo",t),i.addBtnDef("historyUndo",n)}}}})}(jQuery); \ No newline at end of file diff --git a/assets/ext/trumbowyg/plugins/insertaudio/trumbowyg.insertaudio.js b/assets/ext/trumbowyg/plugins/insertaudio/trumbowyg.insertaudio.js new file mode 100644 index 00000000..eeda2db5 --- /dev/null +++ b/assets/ext/trumbowyg/plugins/insertaudio/trumbowyg.insertaudio.js @@ -0,0 +1,100 @@ +/*/* =========================================================== + * trumbowyg.insertaudio.js v1.0 + * InsertAudio plugin for Trumbowyg + * http://alex-d.github.com/Trumbowyg + * =========================================================== + * Author : Adam Hess (AdamHess) + */ + +(function ($) { + 'use strict'; + + var insertAudioOptions = { + src: { + label: 'URL', + required: true + }, + autoplay: { + label: 'AutoPlay', + required: false, + type: 'checkbox' + }, + muted: { + label: 'Muted', + required: false, + type: 'checkbox' + }, + preload: { + label: 'preload options', + required: false + } + }; + + + $.extend(true, $.trumbowyg, { + langs: { + // jshint camelcase:false + en: { + insertAudio: 'Insert Audio' + }, + da: { + insertAudio: 'Indsæt lyd' + }, + fr: { + insertAudio: 'Insérer un son' + }, + ru: { + insertAudio: 'Вставить аудио' + }, + ja: { + insertAudio: '音声の挿入' + }, + tr: { + insertAudio: 'Ses Ekle' + }, + pt_br: { + insertAudio: 'Inserir áudio' + }, + ko: { + insertAudio: '소리 넣기' + }, + // jshint camelcase:true + }, + plugins: { + insertAudio: { + init: function (trumbowyg) { + var btnDef = { + fn: function () { + var insertAudioCallback = function (v) { + // controls should always be show otherwise the audio will + // be invisible defeating the point of a wysiwyg + var html = '