├── docker ├── mysql │ └── db.sql ├── php-fpm │ ├── php-ini-overrides.ini │ └── Dockerfile ├── scripts │ └── docker.sh ├── docker-compose.yml ├── ssl │ ├── material-dashboard.crt │ └── material-dashboard.key └── nginx │ └── nginx.conf ├── web ├── tests │ ├── _data │ │ └── .gitkeep │ ├── _output │ │ └── .gitignore │ ├── acceptance │ │ ├── _bootstrap.php │ │ ├── AboutCest.php │ │ ├── HomeCest.php │ │ ├── LoginCest.php │ │ └── ContactCest.php │ ├── functional │ │ ├── _bootstrap.php │ │ ├── LoginFormCest.php │ │ └── ContactFormCest.php │ ├── unit │ │ ├── _bootstrap.php │ │ └── models │ │ │ ├── UserTest.php │ │ │ ├── LoginFormTest.php │ │ │ └── ContactFormTest.php │ ├── _bootstrap.php │ ├── unit.suite.yml │ ├── acceptance.suite.yml.example │ ├── functional.suite.yml │ ├── bin │ │ ├── yii.bat │ │ └── yii │ └── _support │ │ ├── FunctionalTester.php │ │ ├── UnitTester.php │ │ └── AcceptanceTester.php ├── runtime │ └── .gitignore ├── web │ ├── assets │ │ └── .gitignore │ ├── robots.txt │ ├── scss │ │ ├── material-dashboard │ │ │ ├── variables │ │ │ │ ├── _tooltip.scss │ │ │ │ ├── _code.scss │ │ │ │ ├── _layout.scss │ │ │ │ ├── _drawer.scss │ │ │ │ ├── _body.scss │ │ │ │ ├── _pagination.scss │ │ │ │ ├── _custom-forms.scss │ │ │ │ ├── _snackbar.scss │ │ │ │ ├── _tables.scss │ │ │ │ ├── _brand.scss │ │ │ │ ├── _state.scss │ │ │ │ ├── _spacing.scss │ │ │ │ ├── _card.scss │ │ │ │ ├── _menu.scss │ │ │ │ ├── _dropdown.scss │ │ │ │ ├── _list-group.scss │ │ │ │ ├── _modals.scss │ │ │ │ ├── _bootstrap-material-design-base.scss │ │ │ │ ├── _shadow.scss │ │ │ │ ├── _forms.scss │ │ │ │ └── _nav.scss │ │ │ ├── bootstrap │ │ │ │ └── scss │ │ │ │ │ ├── utilities │ │ │ │ │ ├── _clearfix.scss │ │ │ │ │ ├── _screenreaders.scss │ │ │ │ │ ├── _visibility.scss │ │ │ │ │ ├── _sizing.scss │ │ │ │ │ ├── _float.scss │ │ │ │ │ ├── _align.scss │ │ │ │ │ ├── _background.scss │ │ │ │ │ ├── _position.scss │ │ │ │ │ ├── _embed.scss │ │ │ │ │ ├── _text.scss │ │ │ │ │ ├── _display.scss │ │ │ │ │ ├── _spacing.scss │ │ │ │ │ ├── _borders.scss │ │ │ │ │ └── _flex.scss │ │ │ │ │ ├── _media.scss │ │ │ │ │ ├── mixins │ │ │ │ │ ├── _box-shadow.scss │ │ │ │ │ ├── _size.scss │ │ │ │ │ ├── _clearfix.scss │ │ │ │ │ ├── _visibility.scss │ │ │ │ │ ├── _lists.scss │ │ │ │ │ ├── _text-truncate.scss │ │ │ │ │ ├── _resize.scss │ │ │ │ │ ├── _transition.scss │ │ │ │ │ ├── _float.scss │ │ │ │ │ ├── _nav-divider.scss │ │ │ │ │ ├── _text-hide.scss │ │ │ │ │ ├── _badge.scss │ │ │ │ │ ├── _alert.scss │ │ │ │ │ ├── _text-emphasis.scss │ │ │ │ │ ├── _navbar-align.scss │ │ │ │ │ ├── _list-group.scss │ │ │ │ │ ├── _pagination.scss │ │ │ │ │ ├── _background-variant.scss │ │ │ │ │ ├── _reset-text.scss │ │ │ │ │ ├── _table-row.scss │ │ │ │ │ ├── _border-radius.scss │ │ │ │ │ ├── _screen-reader.scss │ │ │ │ │ ├── _hover.scss │ │ │ │ │ ├── _image.scss │ │ │ │ │ ├── _caret.scss │ │ │ │ │ ├── _grid.scss │ │ │ │ │ ├── _grid-framework.scss │ │ │ │ │ └── _gradients.scss │ │ │ │ │ ├── _jumbotron.scss │ │ │ │ │ ├── _utilities.scss │ │ │ │ │ ├── bootstrap-reboot.scss │ │ │ │ │ ├── _transitions.scss │ │ │ │ │ ├── _root.scss │ │ │ │ │ ├── bootstrap-grid.scss │ │ │ │ │ ├── _progress.scss │ │ │ │ │ ├── _close.scss │ │ │ │ │ ├── bootstrap.scss │ │ │ │ │ ├── _badge.scss │ │ │ │ │ ├── _mixins.scss │ │ │ │ │ ├── _grid.scss │ │ │ │ │ ├── _code.scss │ │ │ │ │ ├── _images.scss │ │ │ │ │ ├── _alert.scss │ │ │ │ │ ├── _breadcrumb.scss │ │ │ │ │ ├── _pagination.scss │ │ │ │ │ ├── _nav.scss │ │ │ │ │ └── _type.scss │ │ │ ├── _social-buttons.scss │ │ │ ├── _images.scss │ │ │ ├── mixins │ │ │ │ ├── _type.scss │ │ │ │ ├── _layout.scss │ │ │ │ ├── _transparency.scss │ │ │ │ ├── _navbar-colors.scss │ │ │ │ ├── _hover.scss │ │ │ │ ├── _variables.scss │ │ │ │ ├── _breakpoints.scss │ │ │ │ ├── _navs.scss │ │ │ │ └── _sidebar-color.scss │ │ │ ├── _mixins.scss │ │ │ ├── cards │ │ │ │ ├── _card-plain.scss │ │ │ │ ├── _card-profile.scss │ │ │ │ └── _card-stats.scss │ │ │ ├── _input-group.scss │ │ │ ├── _ripples.scss │ │ │ ├── _info-areas.scss │ │ │ ├── _example-pages.scss │ │ │ ├── _popover.scss │ │ │ ├── _variables.scss │ │ │ ├── _tooltip.scss │ │ │ ├── _headers.scss │ │ │ ├── _type.scss │ │ │ ├── _core-bootstrap.scss │ │ │ ├── _popups.scss │ │ │ ├── _togglebutton.scss │ │ │ ├── _tabs.scss │ │ │ ├── _footers.scss │ │ │ └── _alerts.scss │ │ └── material-dashboard.scss │ ├── favicon.ico │ ├── img │ │ ├── bg2.jpg │ │ ├── city.jpg │ │ ├── cover.jpg │ │ ├── login.jpg │ │ ├── mask.png │ │ ├── favicon.png │ │ ├── new_logo.png │ │ ├── apple-icon.png │ │ ├── faces │ │ │ ├── marc.jpg │ │ │ ├── avatar.jpg │ │ │ ├── card-profile1-square.jpg │ │ │ └── card-profile2-square.jpg │ │ ├── sidebar-1.jpg │ │ ├── sidebar-2.jpg │ │ ├── sidebar-3.jpg │ │ ├── sidebar-4.jpg │ │ ├── city-profile.jpg │ │ └── favicon │ │ │ ├── favicon-128.png │ │ │ ├── mstile-70x70.png │ │ │ ├── favicon-16x16.png │ │ │ ├── favicon-196x196.png │ │ │ ├── favicon-32x32.png │ │ │ ├── favicon-96x96.png │ │ │ ├── mstile-144x144.png │ │ │ ├── mstile-150x150.png │ │ │ ├── mstile-310x150.png │ │ │ ├── mstile-310x310.png │ │ │ ├── mstile-310x310.png.png │ │ │ ├── apple-touch-icon-57x57.png │ │ │ ├── apple-touch-icon-60x60.png │ │ │ ├── apple-touch-icon-72x72.png │ │ │ ├── apple-touch-icon-76x76.png │ │ │ ├── apple-touch-icon-114x114.png │ │ │ ├── apple-touch-icon-120x120.png │ │ │ ├── apple-touch-icon-144x144.png │ │ │ └── apple-touch-icon-152x152.png │ ├── .htaccess │ ├── index.php │ ├── index-test.php │ └── demo │ │ └── demo.css ├── vagrant │ ├── config │ │ ├── .gitignore │ │ └── vagrant-local.example.yml │ ├── nginx │ │ ├── log │ │ │ └── .gitignore │ │ └── app.conf │ └── provision │ │ ├── always-as-root.sh │ │ ├── once-as-vagrant.sh │ │ └── once-as-root.sh ├── views │ ├── map │ │ └── index.php │ ├── layouts │ │ ├── content.php │ │ └── footer.php │ ├── site │ │ ├── error.php │ │ └── forgot.php │ └── icons │ │ └── index.php ├── config │ ├── params.php │ ├── test_db.php │ ├── db-docker.php │ ├── db-local.php │ ├── test.php │ ├── console.php │ └── web.php ├── docker-compose.yml ├── yii.bat ├── assets │ └── AppAsset.php ├── yii ├── mail │ └── layouts │ │ └── html.php ├── codeception.yml ├── commands │ └── HelloController.php ├── controllers │ ├── IconsController.php │ ├── MapController.php │ ├── TablesController.php │ ├── DashboardController.php │ ├── TypographyController.php │ ├── NotificationsController.php │ └── RtlController.php ├── LICENSE.md ├── models │ ├── UserForgotForm.php │ ├── UserSearch.php │ └── UserLoginForm.php ├── composer.json ├── widgets │ └── Alert.php └── migrations │ └── m200216_223841_create_user_table.php ├── CHANGELOG.md ├── .gitignore ├── composer.json ├── license.md └── ISSUE_TEMPLATE.md /docker/mysql/db.sql: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/tests/_data/.gitkeep: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /web/runtime/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /web/tests/_output/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /web/tests/acceptance/_bootstrap.php: -------------------------------------------------------------------------------- 1 | registerJs( 3 | 'demo.initGoogleMaps();', 4 | yii\web\View::POS_READY, 5 | 'map'); 6 | ?> 7 |
-------------------------------------------------------------------------------- /web/web/img/faces/card-profile1-square.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderseden/material-dashboard-yii2/HEAD/web/web/img/faces/card-profile1-square.jpg -------------------------------------------------------------------------------- /web/web/img/faces/card-profile2-square.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderseden/material-dashboard-yii2/HEAD/web/web/img/faces/card-profile2-square.jpg -------------------------------------------------------------------------------- /web/web/img/favicon/mstile-310x310.png.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderseden/material-dashboard-yii2/HEAD/web/web/img/favicon/mstile-310x310.png.png -------------------------------------------------------------------------------- /web/web/img/favicon/apple-touch-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderseden/material-dashboard-yii2/HEAD/web/web/img/favicon/apple-touch-icon-57x57.png -------------------------------------------------------------------------------- /web/web/img/favicon/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderseden/material-dashboard-yii2/HEAD/web/web/img/favicon/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /web/web/img/favicon/apple-touch-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderseden/material-dashboard-yii2/HEAD/web/web/img/favicon/apple-touch-icon-72x72.png -------------------------------------------------------------------------------- /web/web/img/favicon/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderseden/material-dashboard-yii2/HEAD/web/web/img/favicon/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /web/web/img/favicon/apple-touch-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderseden/material-dashboard-yii2/HEAD/web/web/img/favicon/apple-touch-icon-114x114.png -------------------------------------------------------------------------------- /web/web/img/favicon/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderseden/material-dashboard-yii2/HEAD/web/web/img/favicon/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /web/web/img/favicon/apple-touch-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderseden/material-dashboard-yii2/HEAD/web/web/img/favicon/apple-touch-icon-144x144.png -------------------------------------------------------------------------------- /web/web/img/favicon/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coderseden/material-dashboard-yii2/HEAD/web/web/img/favicon/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/variables/_drawer.scss: -------------------------------------------------------------------------------- 1 | // Drawer 2 | 3 | // Sizing 4 | $bmd-drawer-x-size: 240px !default; 5 | $bmd-drawer-y-size: 100px !default; 6 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/_media.scss: -------------------------------------------------------------------------------- 1 | .media { 2 | display: flex; 3 | align-items: flex-start; 4 | } 5 | 6 | .media-body { 7 | flex: 1; 8 | } 9 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/mixins/_box-shadow.scss: -------------------------------------------------------------------------------- 1 | @mixin box-shadow($shadow...) { 2 | @if $enable-shadows { 3 | box-shadow: $shadow; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to `Material Dashboard` frontend preset for Yii2 will be documented in this file. 4 | 5 | ## Version 1.0.0 6 | - Initial Release -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/mixins/_size.scss: -------------------------------------------------------------------------------- 1 | // Sizing shortcuts 2 | 3 | @mixin size($width, $height: $width) { 4 | width: $width; 5 | height: $height; 6 | } 7 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/mixins/_clearfix.scss: -------------------------------------------------------------------------------- 1 | @mixin clearfix() { 2 | &::after { 3 | display: block; 4 | clear: both; 5 | content: ""; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea 3 | error_log 4 | __MACOSX 5 | .ssh 6 | .composer 7 | .bash_profile 8 | .bash_history 9 | logs 10 | web/vendor 11 | web/config/db.php 12 | web/composer.lock -------------------------------------------------------------------------------- /web/config/params.php: -------------------------------------------------------------------------------- 1 | 'admin@example.com', 5 | 'senderEmail' => 'noreply@example.com', 6 | 'senderName' => 'Example.com mailer', 7 | ]; 8 | 9 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/variables/_body.scss: -------------------------------------------------------------------------------- 1 | // Body 2 | // 3 | // Settings for the `` element. 4 | 5 | $body-bg: #fafafa !default; 6 | //$body-color: $gray-dark !default; 7 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/_social-buttons.scss: -------------------------------------------------------------------------------- 1 | // style for the social buttons from fixed product_plugins (Twitter and Facebook) 2 | 3 | .btn{ 4 | // Social colors 5 | @include bmd-social-buttons(); 6 | } 7 | -------------------------------------------------------------------------------- /web/tests/_bootstrap.php: -------------------------------------------------------------------------------- 1 | amOnPage(Url::toRoute('/site/about')); 10 | $I->see('About', 'h1'); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/mixins/_transition.scss: -------------------------------------------------------------------------------- 1 | @mixin transition($transition...) { 2 | @if $enable-transitions { 3 | @if length($transition) == 0 { 4 | transition: $transition-base; 5 | } @else { 6 | transition: $transition; 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/variables/_tables.scss: -------------------------------------------------------------------------------- 1 | $table-bg-accent: rgba(#000, .03); 2 | $table-border-color: rgba(#000, .06); 3 | $table-bg-hover: rgba(#000, .02); // Grey 100 (on white background) 4 | 5 | $bmd-table-header-font-size: .95rem; 6 | $bmd-table-border-color-inverse: rgba(#fff, .06); 7 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/mixins/_float.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable declaration-no-important 2 | 3 | @mixin float-left { 4 | float: left !important; 5 | } 6 | @mixin float-right { 7 | float: right !important; 8 | } 9 | @mixin float-none { 10 | float: none !important; 11 | } 12 | -------------------------------------------------------------------------------- /web/tests/unit.suite.yml: -------------------------------------------------------------------------------- 1 | # Codeception Test Suite Configuration 2 | 3 | # suite for unit (internal) tests. 4 | # RUN `build` COMMAND AFTER ADDING/REMOVING MODULES. 5 | 6 | class_name: UnitTester 7 | modules: 8 | enabled: 9 | - Asserts 10 | - Yii2: 11 | part: [orm, email, fixtures] 12 | -------------------------------------------------------------------------------- /web/tests/acceptance.suite.yml.example: -------------------------------------------------------------------------------- 1 | class_name: AcceptanceTester 2 | modules: 3 | enabled: 4 | - WebDriver: 5 | url: http://127.0.0.1:8080/ 6 | browser: firefox 7 | - Yii2: 8 | part: orm 9 | entryScript: index-test.php 10 | cleanup: false 11 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/mixins/_nav-divider.scss: -------------------------------------------------------------------------------- 1 | // Horizontal dividers 2 | // 3 | // Dividers (basically an hr) within dropdowns and nav lists 4 | 5 | @mixin nav-divider($color: #e5e5e5) { 6 | height: 0; 7 | margin: ($spacer / 2) 0; 8 | overflow: hidden; 9 | border-top: 1px solid $color; 10 | } 11 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/mixins/_text-hide.scss: -------------------------------------------------------------------------------- 1 | // CSS image replacement 2 | @mixin text-hide() { 3 | // stylelint-disable-next-line font-family-no-missing-generic-family-keyword 4 | font: 0/0 a; 5 | color: transparent; 6 | text-shadow: none; 7 | background-color: transparent; 8 | border: 0; 9 | } 10 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "coderseden/material-dashboard-yii2", 3 | "description": "Material Dashboard Yii2 - Free Frontend Preset for Yii2", 4 | "type": "project", 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "CodersEden", 9 | "email": "hello@coderseden.com" 10 | } 11 | ], 12 | "require": {} 13 | } -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/mixins/_badge.scss: -------------------------------------------------------------------------------- 1 | @mixin badge-variant($bg) { 2 | color: color-yiq($bg); 3 | background-color: $bg; 4 | 5 | &[href] { 6 | @include hover-focus { 7 | color: color-yiq($bg); 8 | text-decoration: none; 9 | background-color: darken($bg, 10%); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/mixins/_alert.scss: -------------------------------------------------------------------------------- 1 | @mixin alert-variant($background, $border, $color) { 2 | color: $color; 3 | @include gradient-bg($background); 4 | border-color: $border; 5 | 6 | hr { 7 | border-top-color: darken($border, 5%); 8 | } 9 | 10 | .alert-link { 11 | color: darken($color, 10%); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /web/vagrant/provision/always-as-root.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | #== Bash helpers == 4 | 5 | function info { 6 | echo " " 7 | echo "--> $1" 8 | echo " " 9 | } 10 | 11 | #== Provision script == 12 | 13 | info "Provision-script user: `whoami`" 14 | 15 | info "Restart web-stack" 16 | service php7.0-fpm restart 17 | service nginx restart 18 | service mysql restart -------------------------------------------------------------------------------- /web/views/layouts/content.php: -------------------------------------------------------------------------------- 1 | 6 | * @link https://www.coderseden.com 7 | * @copyright 2020 Material Dashboard Yii2 (https://www.coderseden.com) 8 | * @license MIT - https://www.coderseden.com 9 | * @since 1.0 10 | */ 11 | ?> 12 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/mixins/_text-emphasis.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable declaration-no-important 2 | 3 | // Typography 4 | 5 | @mixin text-emphasis-variant($parent, $color) { 6 | #{$parent} { 7 | color: $color !important; 8 | } 9 | a#{$parent} { 10 | @include hover-focus { 11 | color: darken($color, 10%) !important; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/utilities/_sizing.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable declaration-no-important 2 | 3 | // Width and height 4 | 5 | @each $prop, $abbrev in (width: w, height: h) { 6 | @each $size, $length in $sizes { 7 | .#{$abbrev}-#{$size} { #{$prop}: $length !important; } 8 | } 9 | } 10 | 11 | .mw-100 { max-width: 100% !important; } 12 | .mh-100 { max-height: 100% !important; } 13 | -------------------------------------------------------------------------------- /web/tests/functional.suite.yml: -------------------------------------------------------------------------------- 1 | # Codeception Test Suite Configuration 2 | 3 | # suite for functional (integration) tests. 4 | # emulate web requests and make application process them. 5 | # (tip: better to use with frameworks). 6 | 7 | # RUN `build` COMMAND AFTER ADDING/REMOVING MODULES. 8 | #basic/web/index.php 9 | class_name: FunctionalTester 10 | modules: 11 | enabled: 12 | - Filesystem 13 | - Yii2 14 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/utilities/_float.scss: -------------------------------------------------------------------------------- 1 | @each $breakpoint in map-keys($grid-breakpoints) { 2 | @include media-breakpoint-up($breakpoint) { 3 | $infix: breakpoint-infix($breakpoint, $grid-breakpoints); 4 | 5 | .float#{$infix}-left { @include float-left; } 6 | .float#{$infix}-right { @include float-right; } 7 | .float#{$infix}-none { @include float-none; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /web/web/index.php: -------------------------------------------------------------------------------- 1 | run(); 13 | -------------------------------------------------------------------------------- /docker/php-fpm/php-ini-overrides.ini: -------------------------------------------------------------------------------- 1 | # 2 | # @package Material Dashboard Yii2 3 | # @author CodersEden 4 | # @link https://www.coderseden.com 5 | # @copyright 2020 Material Dashboard Yii2 (https://www.coderseden.com) 6 | # @license MIT - https://www.coderseden.com 7 | # @since 1.0 8 | upload_max_filesize = 100M 9 | memory_limit = 256M 10 | proxy_read_timeout = 3600 11 | post_max_size = 108M 12 | max_input_vars = 3000 13 | max_execution_time = 300 -------------------------------------------------------------------------------- /web/config/db-docker.php: -------------------------------------------------------------------------------- 1 | 'yii\db\Connection', 5 | 'dsn' => 'mysql:host=material-dashboard-mysql;port=3306;dbname=material-dashboard', 6 | 'username' => 'material-dashboard', 7 | 'password' => 'material-dashboard', 8 | 'charset' => 'utf8', 9 | 10 | // Schema cache options (for production environment) 11 | //'enableSchemaCache' => true, 12 | //'schemaCacheDuration' => 60, 13 | //'schemaCache' => 'cache', 14 | ]; 15 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/mixins/_navbar-align.scss: -------------------------------------------------------------------------------- 1 | // Navbar vertical align 2 | // 3 | // Vertically center elements in the navbar. 4 | // Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` 5 | // to calculate the appropriate top margin. 6 | 7 | // @mixin navbar-vertical-align($element-height) { 8 | // margin-top: (($navbar-height - $element-height) / 2); 9 | // margin-bottom: (($navbar-height - $element-height) / 2); 10 | // } 11 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/mixins/_layout.scss: -------------------------------------------------------------------------------- 1 | // Generates the `.in` style for the generic backdrop used components such as the drawer in overlay mode 2 | @mixin bmd-layout-backdrop-in() { 3 | > .bmd-layout-backdrop { 4 | .in { 5 | visibility: visible; 6 | background-color: rgba(0, 0, 0, 0.5); 7 | } 8 | 9 | @supports (pointer-events: auto) { 10 | &.in { 11 | pointer-events: auto; 12 | opacity: 1; 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /web/tests/acceptance/HomeCest.php: -------------------------------------------------------------------------------- 1 | amOnPage(Url::toRoute('/site/index')); 10 | $I->see('My Company'); 11 | 12 | $I->seeLink('About'); 13 | $I->click('About'); 14 | $I->wait(2); // wait for page to be opened 15 | 16 | $I->see('This is the About page.'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /web/config/db-local.php: -------------------------------------------------------------------------------- 1 | 'yii\db\Connection', 5 | 'dsn' => 'mysql:host=YOUR_DATABASE_PORT;port=YOUR_DATABASE_PORT;dbname=YOUR_DATABASE_NAME', 6 | 'username' => 'YOUR_DATABASE_USERNAME', 7 | 'password' => 'YOUR_DATABASE_PASSWORD', 8 | 'charset' => 'utf8', 9 | 10 | // Schema cache options (for production environment) 11 | //'enableSchemaCache' => true, 12 | //'schemaCacheDuration' => 60, 13 | //'schemaCache' => 'cache', 14 | ]; 15 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/_jumbotron.scss: -------------------------------------------------------------------------------- 1 | .jumbotron { 2 | padding: $jumbotron-padding ($jumbotron-padding / 2); 3 | margin-bottom: $jumbotron-padding; 4 | background-color: $jumbotron-bg; 5 | @include border-radius($border-radius-lg); 6 | 7 | @include media-breakpoint-up(sm) { 8 | padding: ($jumbotron-padding * 2) $jumbotron-padding; 9 | } 10 | } 11 | 12 | .jumbotron-fluid { 13 | padding-right: 0; 14 | padding-left: 0; 15 | @include border-radius(0); 16 | } 17 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/utilities/_align.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable declaration-no-important 2 | 3 | .align-baseline { vertical-align: baseline !important; } // Browser default 4 | .align-top { vertical-align: top !important; } 5 | .align-middle { vertical-align: middle !important; } 6 | .align-bottom { vertical-align: bottom !important; } 7 | .align-text-bottom { vertical-align: text-bottom !important; } 8 | .align-text-top { vertical-align: text-top !important; } 9 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/mixins/_transparency.scss: -------------------------------------------------------------------------------- 1 | // Opacity 2 | 3 | @mixin opacity($opacity) { 4 | opacity: $opacity; 5 | // IE8 filter 6 | $opacity-ie: ($opacity * 100); 7 | filter: #{alpha(opacity=$opacity-ie)}; 8 | } 9 | 10 | @mixin black-filter($opacity){ 11 | top: 0; 12 | left: 0; 13 | height: 100%; 14 | width: 100%; 15 | position: absolute; 16 | background-color: rgba(17,17,17,$opacity); 17 | display: block; 18 | content: ""; 19 | z-index: 1; 20 | } -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/_utilities.scss: -------------------------------------------------------------------------------- 1 | @import "utilities/align"; 2 | @import "utilities/background"; 3 | @import "utilities/borders"; 4 | @import "utilities/clearfix"; 5 | @import "utilities/display"; 6 | @import "utilities/embed"; 7 | @import "utilities/flex"; 8 | @import "utilities/float"; 9 | @import "utilities/position"; 10 | @import "utilities/screenreaders"; 11 | @import "utilities/sizing"; 12 | @import "utilities/spacing"; 13 | @import "utilities/text"; 14 | @import "utilities/visibility"; 15 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/bootstrap-reboot.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Reboot v4.0.0 (https://getbootstrap.com) 3 | * Copyright 2011-2018 The Bootstrap Authors 4 | * Copyright 2011-2018 Twitter, Inc. 5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) 7 | */ 8 | 9 | @import "functions"; 10 | @import "variables"; 11 | @import "mixins"; 12 | @import "reboot"; 13 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/variables/_brand.scss: -------------------------------------------------------------------------------- 1 | // Bootstrap brand color customization 2 | 3 | 4 | /* brand Colors */ 5 | 6 | $brand-primary: $purple-500 !default; 7 | $brand-info: $cyan-500 !default; 8 | $brand-success: $green-500 !default; 9 | $brand-warning: $orange-500 !default; 10 | $brand-danger: $red-500 !default; 11 | $brand-rose: $pink-500 !default; 12 | $brand-inverse: $black-color !default; 13 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/_mixins.scss: -------------------------------------------------------------------------------- 1 | @import "mixins/utilities"; 2 | @import "mixins/breakpoints"; 3 | @import "mixins/animations"; 4 | @import "mixins/type"; 5 | @import "mixins/layout"; 6 | @import "mixins/drawer"; 7 | @import "mixins/forms"; 8 | @import "mixins/buttons"; 9 | @import "mixins/hover"; 10 | @import "mixins/navs"; 11 | @import "mixins/colored-shadows"; 12 | @import "mixins/navbar-colors"; 13 | @import "mixins/alert"; 14 | @import "mixins/sidebar-color"; 15 | @import "mixins/variables"; 16 | @import "mixins/vendor-prefixes"; 17 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/utilities/_background.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable declaration-no-important 2 | 3 | @each $color, $value in $theme-colors { 4 | @include bg-variant(".bg-#{$color}", $value); 5 | } 6 | 7 | @if $enable-gradients { 8 | @each $color, $value in $theme-colors { 9 | @include bg-gradient-variant(".bg-gradient-#{$color}", $value); 10 | } 11 | } 12 | 13 | .bg-white { 14 | background-color: $white !important; 15 | } 16 | 17 | .bg-transparent { 18 | background-color: transparent !important; 19 | } 20 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/mixins/_navbar-colors.scss: -------------------------------------------------------------------------------- 1 | @mixin navbar-colors($color, $link-color) { 2 | color: $link-color; 3 | background-color: $color !important; 4 | @include shadow-navbar-color($color); 5 | 6 | .dropdown-item:hover, 7 | .dropdown-item:focus{ 8 | @include shadow-small-color($color); 9 | background-color: $color; 10 | color: $link-color; 11 | } 12 | 13 | .navbar-toggler{ 14 | .navbar-toggler-icon{ 15 | background-color: $link-color; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /web/web/index-test.php: -------------------------------------------------------------------------------- 1 | run(); 17 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/mixins/_hover.scss: -------------------------------------------------------------------------------- 1 | @mixin bmd-hover-focus-active { 2 | // add the .active to the whole mix of hover-focus-active 3 | &.active { 4 | @content; 5 | } 6 | @include hover-focus-active() { 7 | @content; 8 | } 9 | } 10 | 11 | @mixin transform-translate-y($value){ 12 | -webkit-transform: translate3d(0,$value, 0); 13 | -moz-transform: translate3d(0, $value, 0); 14 | -o-transform: translate3d(0, $value, 0); 15 | -ms-transform: translate3d(0, $value, 0); 16 | transform: translate3d(0, $value, 0); 17 | } 18 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/mixins/_list-group.scss: -------------------------------------------------------------------------------- 1 | // List Groups 2 | 3 | @mixin list-group-item-variant($state, $background, $color) { 4 | .list-group-item-#{$state} { 5 | color: $color; 6 | background-color: $background; 7 | 8 | &.list-group-item-action { 9 | @include hover-focus { 10 | color: $color; 11 | background-color: darken($background, 5%); 12 | } 13 | 14 | &.active { 15 | color: #fff; 16 | background-color: $color; 17 | border-color: $color; 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/variables/_state.scss: -------------------------------------------------------------------------------- 1 | // Form states and alerts 2 | // 3 | // Define colors for form feedback states and, by default, alerts. 4 | $state-success-text: $bmd-inverse !default; 5 | $state-success-bg: $brand-success !default; 6 | 7 | $state-info-text: $bmd-inverse !default; 8 | $state-info-bg: $brand-info !default; 9 | 10 | $state-warning-text: $bmd-inverse !default; 11 | $state-warning-bg: $brand-warning !default; 12 | 13 | $state-danger-text: $bmd-inverse !default; 14 | $state-danger-bg: $brand-danger !default; 15 | 16 | $state-rose-bg: $brand-rose !default; 17 | -------------------------------------------------------------------------------- /web/yii.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem ------------------------------------------------------------- 4 | rem Yii command line bootstrap script for Windows. 5 | rem 6 | rem @author Qiang Xue 7 | rem @link http://www.yiiframework.com/ 8 | rem @copyright Copyright (c) 2008 Yii Software LLC 9 | rem @license http://www.yiiframework.com/license/ 10 | rem ------------------------------------------------------------- 11 | 12 | @setlocal 13 | 14 | set YII_PATH=%~dp0 15 | 16 | if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe 17 | 18 | "%PHP_COMMAND%" "%YII_PATH%yii" %* 19 | 20 | @endlocal 21 | -------------------------------------------------------------------------------- /web/tests/bin/yii.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem ------------------------------------------------------------- 4 | rem Yii command line bootstrap script for Windows. 5 | rem 6 | rem @author Qiang Xue 7 | rem @link http://www.yiiframework.com/ 8 | rem @copyright Copyright (c) 2008 Yii Software LLC 9 | rem @license http://www.yiiframework.com/license/ 10 | rem ------------------------------------------------------------- 11 | 12 | @setlocal 13 | 14 | set YII_PATH=%~dp0 15 | 16 | if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe 17 | 18 | "%PHP_COMMAND%" "%YII_PATH%yii" %* 19 | 20 | @endlocal 21 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/mixins/_pagination.scss: -------------------------------------------------------------------------------- 1 | // Pagination 2 | 3 | @mixin pagination-size($padding-y, $padding-x, $font-size, $line-height, $border-radius) { 4 | .page-link { 5 | padding: $padding-y $padding-x; 6 | font-size: $font-size; 7 | line-height: $line-height; 8 | } 9 | 10 | .page-item { 11 | &:first-child { 12 | .page-link { 13 | @include border-left-radius($border-radius); 14 | } 15 | } 16 | &:last-child { 17 | .page-link { 18 | @include border-right-radius($border-radius); 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /web/vagrant/config/vagrant-local.example.yml: -------------------------------------------------------------------------------- 1 | # Your personal GitHub token 2 | github_token: 3 | # Read more: https://github.com/blog/1509-personal-api-tokens 4 | # You can generate it here: https://github.com/settings/tokens 5 | 6 | # Guest OS timezone 7 | timezone: Europe/London 8 | 9 | # Are we need check box updates for every 'vagrant up'? 10 | box_check_update: false 11 | 12 | # Virtual machine name 13 | machine_name: yii2basic 14 | 15 | # Virtual machine IP 16 | ip: 192.168.83.137 17 | 18 | # Virtual machine CPU cores number 19 | cpus: 1 20 | 21 | # Virtual machine RAM 22 | memory: 1024 23 | -------------------------------------------------------------------------------- /web/assets/AppAsset.php: -------------------------------------------------------------------------------- 1 | 16 | * @since 2.0 17 | */ 18 | class AppAsset extends AssetBundle 19 | { 20 | public $basePath = '@webroot'; 21 | public $baseUrl = '@web'; 22 | public $css = [ 23 | ]; 24 | public $js = [ 25 | ]; 26 | public $depends = [ 27 | ]; 28 | } 29 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/mixins/_background-variant.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable declaration-no-important 2 | 3 | // Contextual backgrounds 4 | 5 | @mixin bg-variant($parent, $color) { 6 | #{$parent} { 7 | background-color: $color !important; 8 | } 9 | a#{$parent}, 10 | button#{$parent} { 11 | @include hover-focus { 12 | background-color: darken($color, 10%) !important; 13 | } 14 | } 15 | } 16 | 17 | @mixin bg-gradient-variant($parent, $color) { 18 | #{$parent} { 19 | background: $color linear-gradient(180deg, mix($body-bg, $color, 15%), $color) repeat-x !important; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /web/yii: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | run(); 21 | exit($exitCode); 22 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/_transitions.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable selector-no-qualifying-type 2 | 3 | .fade { 4 | opacity: 0; 5 | @include transition($transition-fade); 6 | 7 | &.show { 8 | opacity: 1; 9 | } 10 | } 11 | 12 | .collapse { 13 | display: none; 14 | &.show { 15 | display: block; 16 | } 17 | } 18 | 19 | tr { 20 | &.collapse.show { 21 | display: table-row; 22 | } 23 | } 24 | 25 | tbody { 26 | &.collapse.show { 27 | display: table-row-group; 28 | } 29 | } 30 | 31 | .collapsing { 32 | position: relative; 33 | height: 0; 34 | overflow: hidden; 35 | @include transition($transition-collapse); 36 | } 37 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/mixins/_reset-text.scss: -------------------------------------------------------------------------------- 1 | @mixin reset-text { 2 | font-family: $font-family-base; 3 | // We deliberately do NOT reset font-size or word-wrap. 4 | font-style: normal; 5 | font-weight: $font-weight-normal; 6 | line-height: $line-height-base; 7 | text-align: left; // Fallback for where `start` is not supported 8 | text-align: start; // stylelint-disable-line declaration-block-no-duplicate-properties 9 | text-decoration: none; 10 | text-shadow: none; 11 | text-transform: none; 12 | letter-spacing: normal; 13 | word-break: normal; 14 | word-spacing: normal; 15 | white-space: normal; 16 | line-break: auto; 17 | } 18 | -------------------------------------------------------------------------------- /web/tests/acceptance/LoginCest.php: -------------------------------------------------------------------------------- 1 | amOnPage(Url::toRoute('/site/login')); 10 | $I->see('Login', 'h1'); 11 | 12 | $I->amGoingTo('try to login with correct credentials'); 13 | $I->fillField('input[name="LoginForm[username]"]', 'admin'); 14 | $I->fillField('input[name="LoginForm[password]"]', 'admin'); 15 | $I->click('login-button'); 16 | $I->wait(2); // wait for button to be clicked 17 | 18 | $I->expectTo('see user info'); 19 | $I->see('Logout'); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /web/tests/_support/FunctionalTester.php: -------------------------------------------------------------------------------- 1 | 7 | * @link https://www.coderseden.com 8 | * @copyright 2020 Material Dashboard Yii2 (https://www.coderseden.com) 9 | * @license MIT - https://www.coderseden.com 10 | * @since 1.0 11 | */ 12 | 13 | $this->title = $name; 14 | ?> 15 |
16 |
17 |
18 |

title) ?>

19 |

20 |
21 |
22 |
-------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/_root.scss: -------------------------------------------------------------------------------- 1 | :root { 2 | // Custom variable values only support SassScript inside `#{}`. 3 | @each $color, $value in $colors { 4 | --#{$color}: #{$value}; 5 | } 6 | 7 | @each $color, $value in $theme-colors { 8 | --#{$color}: #{$value}; 9 | } 10 | 11 | @each $bp, $value in $grid-breakpoints { 12 | --breakpoint-#{$bp}: #{$value}; 13 | } 14 | 15 | // Use `inspect` for lists so that quoted items keep the quotes. 16 | // See https://github.com/sass/sass/issues/2383#issuecomment-336349172 17 | --font-family-sans-serif: #{inspect($font-family-sans-serif)}; 18 | --font-family-monospace: #{inspect($font-family-monospace)}; 19 | } 20 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/cards/_card-plain.scss: -------------------------------------------------------------------------------- 1 | .card-plain { 2 | background: transparent; 3 | box-shadow: none; 4 | 5 | .card-header:not(.card-avatar) { 6 | margin-left: 0; 7 | margin-right: 0; 8 | } 9 | 10 | .card-body { 11 | padding-left: 5px; 12 | padding-right: 5px; 13 | } 14 | 15 | .card-header-image { 16 | margin: 0 !important; 17 | border-radius: $border-radius-large; 18 | 19 | img { 20 | border-radius: $border-radius-large; 21 | } 22 | } 23 | .card-footer { 24 | padding-left: 5px; 25 | padding-right: 5px; 26 | background-color: transparent; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /web/tests/_support/UnitTester.php: -------------------------------------------------------------------------------- 1 | 4 | # @link https://www.coderseden.com 5 | # @copyright 2020 Material Dashboard Yii2 (https://www.coderseden.com) 6 | # @license MIT - https://www.coderseden.com 7 | # @since 1.0 8 | FROM phpdockerio/php72-fpm:latest 9 | 10 | # Install selected extensions and other stuff 11 | RUN apt-get update \ 12 | && apt-get -y --no-install-recommends install php7.2-mysql php-redis php7.2-bcmath php7.2-gd php7.2-imap php7.2-intl php7.2-ldap php7.2-mbstring php7.2-soap php7.2-tidy \ 13 | && apt-get clean; rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/* 14 | 15 | WORKDIR "/var/www/material-dashboard/web" -------------------------------------------------------------------------------- /web/tests/_support/AcceptanceTester.php: -------------------------------------------------------------------------------- 1 | 8 | beginPage() ?> 9 | 10 | 11 | 12 | 13 | <?= Html::encode($this->title) ?> 14 | head() ?> 15 | 16 | 17 | beginBody() ?> 18 | 19 | endBody() ?> 20 | 21 | 22 | endPage() ?> 23 | -------------------------------------------------------------------------------- /web/vagrant/provision/once-as-vagrant.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | #== Import script args == 4 | 5 | github_token=$(echo "$1") 6 | 7 | #== Bash helpers == 8 | 9 | function info { 10 | echo " " 11 | echo "--> $1" 12 | echo " " 13 | } 14 | 15 | #== Provision script == 16 | 17 | info "Provision-script user: `whoami`" 18 | 19 | info "Configure composer" 20 | composer config --global github-oauth.github.com ${github_token} 21 | echo "Done!" 22 | 23 | info "Install project dependencies" 24 | cd /app 25 | composer --no-progress --prefer-dist install 26 | 27 | info "Create bash-alias 'app' for vagrant user" 28 | echo 'alias app="cd /app"' | tee /home/vagrant/.bash_aliases 29 | 30 | info "Enabling colorized prompt for guest console" 31 | sed -i "s/#force_color_prompt=yes/force_color_prompt=yes/" /home/vagrant/.bashrc 32 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/variables/_card.scss: -------------------------------------------------------------------------------- 1 | // Cards 2 | //$card-spacer-x: 1.25rem !default; 3 | //$card-spacer-y: .75rem !default; 4 | //$card-border-width: 1px !default; 5 | //$card-border-radius: $border-radius !default; 6 | $card-border-color: $gray-lighter !default; // #e5e5e5 7 | //$card-border-radius-inner: $card-border-radius !default; 8 | $card-bg: #fff !default; 9 | $card-cap-bg: $card-bg !default; // #f5f5f5 10 | // 11 | //$card-link-hover-color: #fff !default; 12 | // 13 | //$card-deck-margin: .625rem !default; 14 | // Card 15 | $mdb-card-body-text: $mdb-text-color-primary !default; 16 | $mdb-card-body-background: #fff !default; 17 | $mdb-card-image-headline: #fff !default; 18 | 19 | $text-disabled: #a8a8a8 !default; 20 | $background-disabled: #eaeaea !default; 21 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/mixins/_table-row.scss: -------------------------------------------------------------------------------- 1 | // Tables 2 | 3 | @mixin table-row-variant($state, $background) { 4 | // Exact selectors below required to override `.table-striped` and prevent 5 | // inheritance to nested tables. 6 | .table-#{$state} { 7 | &, 8 | > th, 9 | > td { 10 | background-color: $background; 11 | } 12 | } 13 | 14 | // Hover states for `.table-hover` 15 | // Note: this is not available for cells or rows within `thead` or `tfoot`. 16 | .table-hover { 17 | $hover-background: darken($background, 5%); 18 | 19 | .table-#{$state} { 20 | @include hover { 21 | background-color: $hover-background; 22 | 23 | > td, 24 | > th { 25 | background-color: $hover-background; 26 | } 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/utilities/_position.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable declaration-no-important 2 | 3 | // Common values 4 | 5 | // Sass list not in variables since it's not intended for customization. 6 | $positions: static, relative, absolute, fixed, sticky; 7 | 8 | @each $position in $positions { 9 | .position-#{$position} { position: $position !important; } 10 | } 11 | 12 | // Shorthand 13 | 14 | .fixed-top { 15 | position: fixed; 16 | top: 0; 17 | right: 0; 18 | left: 0; 19 | z-index: $zindex-fixed; 20 | } 21 | 22 | .fixed-bottom { 23 | position: fixed; 24 | right: 0; 25 | bottom: 0; 26 | left: 0; 27 | z-index: $zindex-fixed; 28 | } 29 | 30 | .sticky-top { 31 | @supports (position: sticky) { 32 | position: sticky; 33 | top: 0; 34 | z-index: $zindex-sticky; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/variables/_menu.scss: -------------------------------------------------------------------------------- 1 | $bmd-menu-line-height: 1 !default; // makes it easier to use sizes to match spec 2 | 3 | $bmd-menu-item-min-width: 7rem !default; // Minimum width on mobile = 2 * 56dp = 112dp 4 | $bmd-menu-item-max-width: 17.5rem !default; // Maximum width on mobile (in both portrait and landscape) = 5 * 56dp = 280dp 5 | $bmd-menu-item-min-height: 3rem !default; // 48px 6 | 7 | $bmd-menu-item-padding-right: 1rem !default; 8 | $bmd-menu-item-padding-bottom: .8rem !default; 9 | $bmd-menu-item-padding-left: 1rem !default; 10 | $bmd-menu-item-padding-top: .8rem !default; 11 | 12 | // md and up 13 | $bmd-menu-item-padding-right-md: 1.5rem !default; 14 | $bmd-menu-item-padding-left-md: 1.5rem !default; 15 | 16 | // Menu 17 | $bmd-menu-expand-duration: 0.3s !default; 18 | $bmd-menu-fade-duration: 0.2s !default; 19 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/bootstrap-grid.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Grid v4.0.0 (https://getbootstrap.com) 3 | * Copyright 2011-2018 The Bootstrap Authors 4 | * Copyright 2011-2018 Twitter, Inc. 5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 6 | */ 7 | 8 | @at-root { 9 | @-ms-viewport { width: device-width; } // stylelint-disable-line at-rule-no-vendor-prefix 10 | } 11 | 12 | html { 13 | box-sizing: border-box; 14 | -ms-overflow-style: scrollbar; 15 | } 16 | 17 | *, 18 | *::before, 19 | *::after { 20 | box-sizing: inherit; 21 | } 22 | 23 | @import "functions"; 24 | @import "variables"; 25 | 26 | @import "mixins/breakpoints"; 27 | @import "mixins/grid-framework"; 28 | @import "mixins/grid"; 29 | 30 | @import "grid"; 31 | @import "utilities/display"; 32 | @import "utilities/flex"; 33 | -------------------------------------------------------------------------------- /web/tests/bin/yii: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | [ 21 | 'db' => require __DIR__ . '/../../config/test_db.php' 22 | ] 23 | ] 24 | ); 25 | 26 | 27 | $application = new yii\console\Application($config); 28 | $exitCode = $application->run(); 29 | exit($exitCode); 30 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/variables/_dropdown.scss: -------------------------------------------------------------------------------- 1 | // Dropdowns 2 | // 3 | // Dropdown menu container and contents. 4 | 5 | //$dropdown-bg: #fff !default; 6 | //$dropdown-border-color: rgba(0,0,0,.15) !default; 7 | //$dropdown-border-width: $border-width !default; 8 | //$dropdown-divider-bg: #e5e5e5 !default; 9 | $dropdown-box-shadow: $bmd-shadow-2dp !default; //0 6px 12px rgba(0,0,0,.175) !default; 10 | // 11 | //$dropdown-link-color: $gray-dark !default; 12 | //$dropdown-link-hover-color: darken($gray-dark, 5%) !default; 13 | //$dropdown-link-hover-bg: #f5f5f5 !default; 14 | // 15 | //$dropdown-link-active-color: $component-active-color !default; 16 | //$dropdown-link-active-bg: $component-active-bg !default; 17 | // 18 | //$dropdown-link-disabled-color: $gray-light !default; 19 | // 20 | //$dropdown-header-color: $gray-light !default; 21 | -------------------------------------------------------------------------------- /web/codeception.yml: -------------------------------------------------------------------------------- 1 | actor: Tester 2 | bootstrap: _bootstrap.php 3 | paths: 4 | tests: tests 5 | log: tests/_output 6 | data: tests/_data 7 | helpers: tests/_support 8 | settings: 9 | memory_limit: 1024M 10 | colors: true 11 | modules: 12 | config: 13 | Yii2: 14 | configFile: 'config/test.php' 15 | 16 | # To enable code coverage: 17 | #coverage: 18 | # #c3_url: http://localhost:8080/index-test.php/ 19 | # enabled: true 20 | # #remote: true 21 | # #remote_config: '../codeception.yml' 22 | # whitelist: 23 | # include: 24 | # - models/* 25 | # - controllers/* 26 | # - commands/* 27 | # - mail/* 28 | # blacklist: 29 | # include: 30 | # - assets/* 31 | # - config/* 32 | # - runtime/* 33 | # - vendor/* 34 | # - views/* 35 | # - web/* 36 | # - tests/* 37 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/mixins/_border-radius.scss: -------------------------------------------------------------------------------- 1 | // Single side border-radius 2 | 3 | @mixin border-radius($radius: $border-radius) { 4 | @if $enable-rounded { 5 | border-radius: $radius; 6 | } 7 | } 8 | 9 | @mixin border-top-radius($radius) { 10 | @if $enable-rounded { 11 | border-top-left-radius: $radius; 12 | border-top-right-radius: $radius; 13 | } 14 | } 15 | 16 | @mixin border-right-radius($radius) { 17 | @if $enable-rounded { 18 | border-top-right-radius: $radius; 19 | border-bottom-right-radius: $radius; 20 | } 21 | } 22 | 23 | @mixin border-bottom-radius($radius) { 24 | @if $enable-rounded { 25 | border-bottom-right-radius: $radius; 26 | border-bottom-left-radius: $radius; 27 | } 28 | } 29 | 30 | @mixin border-left-radius($radius) { 31 | @if $enable-rounded { 32 | border-top-left-radius: $radius; 33 | border-bottom-left-radius: $radius; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /web/commands/HelloController.php: -------------------------------------------------------------------------------- 1 | 19 | * @since 2.0 20 | */ 21 | class HelloController extends Controller 22 | { 23 | /** 24 | * This command echoes what you have entered as the message. 25 | * @param string $message the message to be echoed. 26 | * @return int Exit code 27 | */ 28 | public function actionIndex($message = 'hello world') 29 | { 30 | echo $message . "\n"; 31 | 32 | return ExitCode::OK; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/_input-group.scss: -------------------------------------------------------------------------------- 1 | // ----------------------------------------- 2 | // input-group and input-group-addon styles 3 | // note: form-groups are not required 4 | // 5 | @mixin input-group-button-variation($vertical-padding) { 6 | .input-group-btn { 7 | .btn { 8 | //margin: 0 0 $vertical-padding 0; 9 | } 10 | } 11 | } 12 | 13 | // default margin - no form-group required 14 | @include input-group-button-variation(input-padding-y); 15 | 16 | .bmd-form-group-sm { 17 | @include input-group-button-variation($input-padding-y-sm); 18 | } 19 | 20 | .bmd-form-group-lg { 21 | @include input-group-button-variation($input-padding-y-lg); 22 | } 23 | 24 | .input-group { 25 | // may be in or outside of form-group 26 | 27 | .input-group-text { 28 | display: flex; 29 | justify-content: center; 30 | align-items: center; 31 | padding: 0 15px 0 15px; 32 | background-color: transparent; 33 | border-color: transparent; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/mixins/_screen-reader.scss: -------------------------------------------------------------------------------- 1 | // Only display content to screen readers 2 | // 3 | // See: http://a11yproject.com/posts/how-to-hide-content/ 4 | // See: https://hugogiraudel.com/2016/10/13/css-hide-and-seek/ 5 | 6 | @mixin sr-only { 7 | position: absolute; 8 | width: 1px; 9 | height: 1px; 10 | padding: 0; 11 | overflow: hidden; 12 | clip: rect(0, 0, 0, 0); 13 | white-space: nowrap; 14 | clip-path: inset(50%); 15 | border: 0; 16 | } 17 | 18 | // Use in conjunction with .sr-only to only display content when it's focused. 19 | // 20 | // Useful for "Skip to main content" links; see https://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 21 | // 22 | // Credit: HTML5 Boilerplate 23 | 24 | @mixin sr-only-focusable { 25 | &:active, 26 | &:focus { 27 | position: static; 28 | width: auto; 29 | height: auto; 30 | overflow: visible; 31 | clip: auto; 32 | white-space: normal; 33 | clip-path: none; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/mixins/_hover.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable indentation 2 | 3 | // Hover mixin and `$enable-hover-media-query` are deprecated. 4 | // 5 | // Origally added during our alphas and maintained during betas, this mixin was 6 | // designed to prevent `:hover` stickiness on iOS—an issue where hover styles 7 | // would persist after initial touch. 8 | // 9 | // For backward compatibility, we've kept these mixins and updated them to 10 | // always return their regular psuedo-classes instead of a shimmed media query. 11 | // 12 | // Issue: https://github.com/twbs/bootstrap/issues/25195 13 | 14 | @mixin hover { 15 | &:hover { @content; } 16 | } 17 | 18 | @mixin hover-focus { 19 | &:hover, 20 | &:focus { 21 | @content; 22 | } 23 | } 24 | 25 | @mixin plain-hover-focus { 26 | &, 27 | &:hover, 28 | &:focus { 29 | @content; 30 | } 31 | } 32 | 33 | @mixin hover-focus-active { 34 | &:hover, 35 | &:focus, 36 | &:active { 37 | @content; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/mixins/_variables.scss: -------------------------------------------------------------------------------- 1 | //== Buttons 2 | // 3 | //## For each of Bootstrap's buttons, define text, background and border color. 4 | 5 | $opacity-gray-3: rgba(222,222,222, .3) !default; 6 | $opacity-gray-5: rgba(222,222,222, .5) !default; 7 | $opacity-gray-8: rgba(222,222,222, .8) !default; 8 | 9 | $opacity-5: rgba(255,255,255, .5) !default; 10 | $opacity-8: rgba(255,255,255, .8) !default; 11 | 12 | $opacity-1: rgba(255,255,255, .1) !default; 13 | $opacity-2: rgba(255,255,255, .2) !default; 14 | 15 | //== Components 16 | // 17 | 18 | $topbar-x: topbar-x !default; 19 | $topbar-back: topbar-back !default; 20 | $bottombar-x: bottombar-x !default; 21 | $bottombar-back: bottombar-back !default; 22 | 23 | // Sidebar variables 24 | $sidebar-width: calc(100% - 260px) !default; 25 | $sidebar-mini-width: calc(100% - 80px) !default; 26 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/utilities/_embed.scss: -------------------------------------------------------------------------------- 1 | // Credit: Nicolas Gallagher and SUIT CSS. 2 | 3 | .embed-responsive { 4 | position: relative; 5 | display: block; 6 | width: 100%; 7 | padding: 0; 8 | overflow: hidden; 9 | 10 | &::before { 11 | display: block; 12 | content: ""; 13 | } 14 | 15 | .embed-responsive-item, 16 | iframe, 17 | embed, 18 | object, 19 | video { 20 | position: absolute; 21 | top: 0; 22 | bottom: 0; 23 | left: 0; 24 | width: 100%; 25 | height: 100%; 26 | border: 0; 27 | } 28 | } 29 | 30 | .embed-responsive-21by9 { 31 | &::before { 32 | padding-top: percentage(9 / 21); 33 | } 34 | } 35 | 36 | .embed-responsive-16by9 { 37 | &::before { 38 | padding-top: percentage(9 / 16); 39 | } 40 | } 41 | 42 | .embed-responsive-4by3 { 43 | &::before { 44 | padding-top: percentage(3 / 4); 45 | } 46 | } 47 | 48 | .embed-responsive-1by1 { 49 | &::before { 50 | padding-top: percentage(1 / 1); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/cards/_card-profile.scss: -------------------------------------------------------------------------------- 1 | .card-profile{ 2 | margin-top: 30px; 3 | text-align: center; 4 | 5 | 6 | .card-avatar { 7 | margin: -50px auto 0; 8 | border-radius: 50%; 9 | overflow: hidden; 10 | padding: 0; 11 | 12 | @include shadow-big(); 13 | 14 | & + .card-body { 15 | margin-top: 15px; 16 | } 17 | img { 18 | width: 100%; 19 | height: auto; 20 | } 21 | } 22 | 23 | .card-body + .card-footer { 24 | margin-top: -15px; 25 | } 26 | 27 | .card-footer { 28 | .btn.btn-just-icon { 29 | font-size: 20px; 30 | padding: 12px 12px; 31 | line-height: 1em; 32 | } 33 | } 34 | 35 | &.card-plain { 36 | .card-avatar { 37 | margin-top: 0; 38 | } 39 | } 40 | 41 | .card-header:not([class*="card-header-"]){ 42 | background: transparent; 43 | } 44 | .card-avatar { 45 | max-width: 130px; 46 | max-height: 130px; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/_progress.scss: -------------------------------------------------------------------------------- 1 | @keyframes progress-bar-stripes { 2 | from { background-position: $progress-height 0; } 3 | to { background-position: 0 0; } 4 | } 5 | 6 | .progress { 7 | display: flex; 8 | height: $progress-height; 9 | overflow: hidden; // force rounded corners by cropping it 10 | font-size: $progress-font-size; 11 | background-color: $progress-bg; 12 | @include border-radius($progress-border-radius); 13 | @include box-shadow($progress-box-shadow); 14 | } 15 | 16 | .progress-bar { 17 | display: flex; 18 | flex-direction: column; 19 | justify-content: center; 20 | color: $progress-bar-color; 21 | text-align: center; 22 | background-color: $progress-bar-bg; 23 | @include transition($progress-bar-transition); 24 | } 25 | 26 | .progress-bar-striped { 27 | @include gradient-striped(); 28 | background-size: $progress-height $progress-height; 29 | } 30 | 31 | .progress-bar-animated { 32 | animation: progress-bar-stripes $progress-bar-animation-timing; 33 | } 34 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/variables/_list-group.scss: -------------------------------------------------------------------------------- 1 | // List group 2 | 3 | $list-group-bg: inherit !default; // #fff 4 | //$list-group-border-color: #ddd !default; 5 | $list-group-border-width: 0 !default; // $border-width 6 | $list-group-border-radius: 0 !default; // $border-radius 7 | // 8 | //$list-group-hover-bg: #f5f5f5 !default; 9 | //$list-group-active-color: $component-active-color !default; 10 | //$list-group-active-bg: $component-active-bg !default; 11 | //$list-group-active-border: $list-group-active-bg !default; 12 | //$list-group-active-text-color: lighten($list-group-active-bg, 40%) !default; 13 | // 14 | //$list-group-disabled-color: $gray-light !default; 15 | //$list-group-disabled-bg: $gray-lighter !default; 16 | //$list-group-disabled-text-color: $list-group-disabled-color !default; 17 | // 18 | //$list-group-link-color: #555 !default; 19 | //$list-group-link-hover-color: $list-group-link-color !default; 20 | //$list-group-link-heading-color: #333 !default; 21 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/_ripples.scss: -------------------------------------------------------------------------------- 1 | // marker class (used as a selector for one-off elements to decorate) 2 | .ripple { 3 | position: relative; 4 | } 5 | 6 | .ripple-container { 7 | position: absolute; 8 | top: 0; 9 | left: 0; 10 | z-index: 1; 11 | width: 100%; 12 | height: 100%; 13 | overflow: hidden; 14 | pointer-events: none; 15 | border-radius: inherit; 16 | 17 | .ripple-decorator { 18 | position: absolute; 19 | width: 20px; 20 | height: 20px; 21 | margin-top: -10px; 22 | margin-left: -10px; 23 | pointer-events: none; 24 | background-color: rgba($black, 0.05); 25 | border-radius: 100%; 26 | opacity: 0; 27 | transform: scale(1); 28 | transform-origin: 50%; 29 | 30 | &.ripple-on { 31 | opacity: 0.1; 32 | transition: opacity 0.15s ease-in 0s, 33 | transform 0.5s cubic-bezier(0.4, 0, 0.2, 1) 0.1s; 34 | } 35 | 36 | &.ripple-out { 37 | opacity: 0; 38 | transition: opacity 0.1s linear 0s !important; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/_close.scss: -------------------------------------------------------------------------------- 1 | .close { 2 | float: right; 3 | font-size: $close-font-size; 4 | font-weight: $close-font-weight; 5 | line-height: 1; 6 | color: $close-color; 7 | text-shadow: $close-text-shadow; 8 | opacity: .5; 9 | 10 | @include hover-focus { 11 | color: $close-color; 12 | text-decoration: none; 13 | opacity: .75; 14 | } 15 | 16 | // Opinionated: add "hand" cursor to non-disabled .close elements 17 | &:not(:disabled):not(.disabled) { 18 | cursor: pointer; 19 | } 20 | } 21 | 22 | // Additional properties for button version 23 | // iOS requires the button element instead of an anchor tag. 24 | // If you want the anchor version, it requires `href="#"`. 25 | // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile 26 | 27 | // stylelint-disable property-no-vendor-prefix, selector-no-qualifying-type 28 | button.close { 29 | padding: 0; 30 | background-color: transparent; 31 | border: 0; 32 | -webkit-appearance: none; 33 | } 34 | // stylelint-enable 35 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/mixins/_breakpoints.scss: -------------------------------------------------------------------------------- 1 | // case where behavior is responsive, or with a marker class 2 | @mixin media-breakpoint-down-or($breakpoint, $name) { 3 | #{unquote($name)} { 4 | @content; 5 | } 6 | 7 | @include media-breakpoint-down($breakpoint) { 8 | @content; 9 | } 10 | } 11 | 12 | // case where behavior is responsive, or with a marker class 13 | @mixin media-breakpoint-up-or($breakpoint, $name) { 14 | #{unquote($name)} { 15 | @content; 16 | } 17 | 18 | @include media-breakpoint-up($breakpoint) { 19 | @content; 20 | } 21 | } 22 | 23 | // Name of the previous breakpoint, or null 24 | // 25 | // >> breakpoint-next(sm) 26 | // xs 27 | // >> breakpoint-next(sm, (xs: 0, sm: 544px, md: 768px)) 28 | // xs 29 | // >> breakpoint-next(sm, $breakpoint-names: (xs sm md)) 30 | // xs 31 | @function breakpoint-previous($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) { 32 | $n: index($breakpoint-names, $name); 33 | @return if($n > 1, nth($breakpoint-names, $n - 1), null); 34 | } 35 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/cards/_card-stats.scss: -------------------------------------------------------------------------------- 1 | .card-stats{ 2 | .card-header{ 3 | &.card-header-icon, 4 | &.card-header-text{ 5 | text-align: right; 6 | } 7 | 8 | .card-icon + .card-title, 9 | .card-icon + .card-category{ 10 | padding-top: 10px; 11 | } 12 | 13 | &.card-header-icon .card-title, 14 | &.card-header-text .card-title, 15 | &.card-header-icon .card-category, 16 | &.card-header-text .card-category { 17 | margin: 0; 18 | } 19 | .card-category { 20 | margin-bottom: 0; 21 | margin-top: 0; 22 | 23 | &:not([class*="text-"]){ 24 | color: $gray-color; 25 | font-size: $font-paragraph; 26 | } 27 | } 28 | 29 | & + .card-footer{ 30 | border-top: 1px solid #eee; 31 | margin-top: 20px; 32 | } 33 | 34 | &.card-header-icon i { 35 | font-size: 36px; 36 | line-height: 56px; 37 | width: 56px; 38 | height: 56px; 39 | text-align: center; 40 | } 41 | } 42 | 43 | .card-body { 44 | text-align: right; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 CodersEden (https://www.coderseden.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/bootstrap.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v4.0.0 (https://getbootstrap.com) 3 | * Copyright 2011-2018 The Bootstrap Authors 4 | * Copyright 2011-2018 Twitter, Inc. 5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 6 | */ 7 | 8 | @import "functions"; 9 | @import "variables"; 10 | @import "mixins"; 11 | @import "root"; 12 | @import "reboot"; 13 | @import "type"; 14 | @import "images"; 15 | @import "code"; 16 | @import "grid"; 17 | @import "tables"; 18 | @import "forms"; 19 | @import "buttons"; 20 | @import "transitions"; 21 | @import "dropdown"; 22 | @import "button-group"; 23 | @import "input-group"; 24 | @import "custom-forms"; 25 | @import "nav"; 26 | @import "navbar"; 27 | @import "card"; 28 | @import "breadcrumb"; 29 | @import "pagination"; 30 | @import "badge"; 31 | @import "jumbotron"; 32 | @import "alert"; 33 | @import "progress"; 34 | @import "media"; 35 | @import "list-group"; 36 | @import "close"; 37 | @import "modal"; 38 | @import "tooltip"; 39 | @import "popover"; 40 | @import "carousel"; 41 | @import "utilities"; 42 | @import "print"; 43 | -------------------------------------------------------------------------------- /web/controllers/IconsController.php: -------------------------------------------------------------------------------- 1 | 6 | * @link https://www.coderseden.com 7 | * @copyright 2020 Material Dashboard Yii2 (https://www.coderseden.com) 8 | * @license MIT - https://www.coderseden.com 9 | * @since 1.0 10 | */ 11 | namespace app\controllers; 12 | 13 | /** 14 | * Class IconsController 15 | * @package app\controllers 16 | */ 17 | class IconsController extends \yii\web\Controller 18 | { 19 | /** 20 | * @param \yii\base\Action $action 21 | * 22 | * @return bool|void 23 | * @throws \yii\web\BadRequestHttpException 24 | */ 25 | public function beforeAction( $action ) 26 | { 27 | if ( \Yii::$app->getUser()->isGuest ) { 28 | return \Yii::$app->getResponse()->redirect( \yii\helpers\Url::to(['/']) )->send(); 29 | } 30 | return parent::beforeAction( $action ); // TODO: Change the autogenerated stub 31 | } 32 | 33 | /** 34 | * @return string 35 | */ 36 | public function actionIndex() 37 | { 38 | return $this->render('index', []); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /web/controllers/MapController.php: -------------------------------------------------------------------------------- 1 | 6 | * @link https://www.coderseden.com 7 | * @copyright 2020 Material Dashboard Yii2 (https://www.coderseden.com) 8 | * @license MIT - https://www.coderseden.com 9 | * @since 1.0 10 | */ 11 | namespace app\controllers; 12 | 13 | /** 14 | * Class MapController 15 | * @package app\controllers 16 | */ 17 | class MapController extends \yii\web\Controller 18 | { 19 | /** 20 | * @param \yii\base\Action $action 21 | * 22 | * @return bool|void 23 | * @throws \yii\web\BadRequestHttpException 24 | */ 25 | public function beforeAction( $action ) 26 | { 27 | if ( \Yii::$app->getUser()->isGuest ) { 28 | return \Yii::$app->getResponse()->redirect( \yii\helpers\Url::to(['/']) )->send(); 29 | } 30 | return parent::beforeAction( $action ); // TODO: Change the autogenerated stub 31 | } 32 | 33 | 34 | /** 35 | * @return string 36 | */ 37 | public function actionIndex() 38 | { 39 | return $this->render('index', []); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /web/controllers/TablesController.php: -------------------------------------------------------------------------------- 1 | 6 | * @link https://www.coderseden.com 7 | * @copyright 2020 Material Dashboard Yii2 (https://www.coderseden.com) 8 | * @license MIT - https://www.coderseden.com 9 | * @since 1.0 10 | */ 11 | namespace app\controllers; 12 | 13 | /** 14 | * Class TablesController 15 | * @package app\controllers 16 | */ 17 | class TablesController extends \yii\web\Controller 18 | { 19 | /** 20 | * @param \yii\base\Action $action 21 | * 22 | * @return bool|void 23 | * @throws \yii\web\BadRequestHttpException 24 | */ 25 | public function beforeAction( $action ) 26 | { 27 | if ( \Yii::$app->getUser()->isGuest ) { 28 | return \Yii::$app->getResponse()->redirect( \yii\helpers\Url::to(['/']) )->send(); 29 | } 30 | return parent::beforeAction( $action ); // TODO: Change the autogenerated stub 31 | } 32 | 33 | /** 34 | * @return string 35 | */ 36 | public function actionIndex() 37 | { 38 | return $this->render('index', []); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/_info-areas.scss: -------------------------------------------------------------------------------- 1 | .info{ 2 | max-width: 360px; 3 | margin: 0 auto; 4 | padding: 70px 0 30px; 5 | 6 | .icon{ 7 | color: $gray-color; 8 | 9 | > i{ 10 | font-size: 3.85rem; 11 | } 12 | } 13 | .info-title{ 14 | color: $black-color; 15 | margin: 0.875rem * 2 0 0.875rem; 16 | } 17 | p{ 18 | color: $gray-color; 19 | } 20 | } 21 | 22 | .info-horizontal{ 23 | .icon{ 24 | float: left; 25 | margin-top: 24px; 26 | margin-right: 10px; 27 | 28 | >i{ 29 | font-size: $font-size-h2; 30 | } 31 | } 32 | .description{ 33 | overflow: hidden; 34 | } 35 | 36 | } 37 | 38 | .icon { 39 | &.icon-primary { 40 | color: $brand-primary; 41 | } 42 | &.icon-info { 43 | color: $brand-info; 44 | } 45 | &.icon-success { 46 | color: $brand-success; 47 | } 48 | &.icon-warning { 49 | color: $brand-warning; 50 | } 51 | &.icon-danger { 52 | color: $brand-danger; 53 | } 54 | &.icon-rose { 55 | color: $brand-rose; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /web/controllers/DashboardController.php: -------------------------------------------------------------------------------- 1 | 6 | * @link https://www.coderseden.com 7 | * @copyright 2020 Material Dashboard Yii2 (https://www.coderseden.com) 8 | * @license MIT - https://www.coderseden.com 9 | * @since 1.0 10 | */ 11 | namespace app\controllers; 12 | 13 | /** 14 | * Class DashboardController 15 | * @package app\controllers 16 | */ 17 | class DashboardController extends \yii\web\Controller 18 | { 19 | /** 20 | * @param \yii\base\Action $action 21 | * 22 | * @return bool|void 23 | * @throws \yii\web\BadRequestHttpException 24 | */ 25 | public function beforeAction( $action ) 26 | { 27 | if ( \Yii::$app->getUser()->isGuest ) { 28 | return \Yii::$app->getResponse()->redirect( \yii\helpers\Url::to(['/']) )->send(); 29 | } 30 | return parent::beforeAction( $action ); // TODO: Change the autogenerated stub 31 | } 32 | 33 | /** 34 | * @return string 35 | */ 36 | public function actionIndex() 37 | { 38 | return $this->render('index', []); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /web/controllers/TypographyController.php: -------------------------------------------------------------------------------- 1 | 6 | * @link https://www.coderseden.com 7 | * @copyright 2020 Material Dashboard Yii2 (https://www.coderseden.com) 8 | * @license MIT - https://www.coderseden.com 9 | * @since 1.0 10 | */ 11 | namespace app\controllers; 12 | 13 | /** 14 | * Class TypographyController 15 | * @package app\controllers 16 | */ 17 | class TypographyController extends \yii\web\Controller 18 | { 19 | /** 20 | * @param \yii\base\Action $action 21 | * 22 | * @return bool|void 23 | * @throws \yii\web\BadRequestHttpException 24 | */ 25 | public function beforeAction( $action ) 26 | { 27 | if ( \Yii::$app->getUser()->isGuest ) { 28 | return \Yii::$app->getResponse()->redirect( \yii\helpers\Url::to(['/']) )->send(); 29 | } 30 | return parent::beforeAction( $action ); // TODO: Change the autogenerated stub 31 | } 32 | 33 | /** 34 | * @return string 35 | */ 36 | public function actionIndex() 37 | { 38 | return $this->render('index', []); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /web/controllers/NotificationsController.php: -------------------------------------------------------------------------------- 1 | 6 | * @link https://www.coderseden.com 7 | * @copyright 2020 Material Dashboard Yii2 (https://www.coderseden.com) 8 | * @license MIT - https://www.coderseden.com 9 | * @since 1.0 10 | */ 11 | namespace app\controllers; 12 | 13 | /** 14 | * Class NotificationsController 15 | * @package app\controllers 16 | */ 17 | class NotificationsController extends \yii\web\Controller 18 | { 19 | /** 20 | * @param \yii\base\Action $action 21 | * 22 | * @return bool|void 23 | * @throws \yii\web\BadRequestHttpException 24 | */ 25 | public function beforeAction( $action ) 26 | { 27 | if ( \Yii::$app->getUser()->isGuest ) { 28 | return \Yii::$app->getResponse()->redirect( \yii\helpers\Url::to(['/']) )->send(); 29 | } 30 | return parent::beforeAction( $action ); // TODO: Change the autogenerated stub 31 | } 32 | 33 | /** 34 | * @return string 35 | */ 36 | public function actionIndex() 37 | { 38 | return $this->render('index', []); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /web/controllers/RtlController.php: -------------------------------------------------------------------------------- 1 | 6 | * @link https://www.coderseden.com 7 | * @copyright 2020 Material Dashboard Yii2 (https://www.coderseden.com) 8 | * @license MIT - https://www.coderseden.com 9 | * @since 1.0 10 | */ 11 | namespace app\controllers; 12 | 13 | /** 14 | * Class RtlController 15 | * @package app\controllers 16 | */ 17 | class RtlController extends \yii\web\Controller 18 | { 19 | /** 20 | * @param \yii\base\Action $action 21 | * 22 | * @return bool|void 23 | * @throws \yii\web\BadRequestHttpException 24 | */ 25 | public function beforeAction( $action ) 26 | { 27 | if ( \Yii::$app->getUser()->isGuest ) { 28 | return \Yii::$app->getResponse()->redirect( \yii\helpers\Url::to(['/']) )->send(); 29 | } 30 | return parent::beforeAction( $action ); // TODO: Change the autogenerated stub 31 | } 32 | 33 | /** 34 | * @return string 35 | */ 36 | public function actionIndex() 37 | { 38 | return $this->renderFile(\Yii::getAlias('@app/views/rtl/index.php')); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/_example-pages.scss: -------------------------------------------------------------------------------- 1 | .card-signup { 2 | .card-header { 3 | .social-line { 4 | .btn { 5 | color: $white-color; 6 | } 7 | } 8 | } 9 | .text-divider { 10 | margin-top: 30px; 11 | margin-bottom: 0px; 12 | text-align: center; 13 | } 14 | } 15 | 16 | .signup-page { 17 | .page-header { 18 | min-height: 100vh; 19 | height: auto; 20 | display: inherit; 21 | 22 | .container{ 23 | padding-top: 20vh; 24 | } 25 | } 26 | 27 | .card-signup { 28 | border-radius: $border-radius-base * 2; 29 | @include shadow-16dp(); 30 | margin-bottom: 100px; 31 | padding: 40px 0px; 32 | 33 | } 34 | .info-horizontal { 35 | padding: 0px 0px 20px; 36 | } 37 | 38 | .social { 39 | .btn { 40 | margin: 5px; 41 | } 42 | h4 { 43 | margin-top: 20px; 44 | } 45 | } 46 | .footer { 47 | .container { 48 | padding: 0; 49 | } 50 | .copyright, 51 | a{ 52 | color: $white-color; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /docker/scripts/docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # @package Material Dashboard Yii2 4 | # @author CodersEden 5 | # @link https://www.coderseden.com 6 | # @copyright 2020 Material Dashboard Yii2 (https://www.coderseden.com) 7 | # @license MIT - https://www.coderseden.com 8 | # @since 1.0 9 | 10 | # default values for command line variables 11 | ACTION="" 12 | 13 | # arguments init 14 | for i in "$@" 15 | do 16 | case $i in 17 | up) 18 | ACTION="up" 19 | shift # past argument=value 20 | ;; 21 | down) 22 | ACTION="down" 23 | shift # past argument=value 24 | ;; 25 | remove) 26 | ACTION="remove" 27 | shift # past argument=value 28 | ;; 29 | *) 30 | # unknown option 31 | ;; 32 | esac 33 | done 34 | 35 | if [[ "$ACTION" = "up" ]]; then 36 | docker-compose up --build 37 | fi 38 | 39 | if [[ "$ACTION" = "down" ]]; then 40 | docker kill $(docker ps -q) 41 | fi 42 | 43 | if [[ "$ACTION" = "remove" ]]; then 44 | docker rm -f $(docker ps -q -a) 45 | fi -------------------------------------------------------------------------------- /web/tests/acceptance/ContactCest.php: -------------------------------------------------------------------------------- 1 | amOnPage(Url::toRoute('/site/contact')); 10 | } 11 | 12 | public function contactPageWorks(AcceptanceTester $I) 13 | { 14 | $I->wantTo('ensure that contact page works'); 15 | $I->see('Contact', 'h1'); 16 | } 17 | 18 | public function contactFormCanBeSubmitted(AcceptanceTester $I) 19 | { 20 | $I->amGoingTo('submit contact form with correct data'); 21 | $I->fillField('#contactform-name', 'tester'); 22 | $I->fillField('#contactform-email', 'tester@example.com'); 23 | $I->fillField('#contactform-subject', 'test subject'); 24 | $I->fillField('#contactform-body', 'test content'); 25 | $I->fillField('#contactform-verifycode', 'testme'); 26 | 27 | $I->click('contact-button'); 28 | 29 | $I->wait(2); // wait for button to be clicked 30 | 31 | $I->dontSeeElement('#contact-form'); 32 | $I->see('Thank you for contacting us. We will respond to you as soon as possible.'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | 3 | Please answer the following questions for yourself before submitting an issue. 4 | 5 | - [ ] I am running the latest version 6 | - [ ] I checked the documentation and found no answer 7 | - [ ] I checked to make sure that this issue has not already been filed 8 | - [ ] I'm reporting the issue to the correct repository (for multi-repository projects) 9 | 10 | # Expected Behavior 11 | 12 | Please describe the behavior you are expecting 13 | 14 | # Current Behavior 15 | 16 | What is the current behavior? 17 | 18 | # Failure Information (for bugs) 19 | 20 | Please help provide information about the failure if this is a bug. If it is not a bug, please remove the rest of this template. 21 | 22 | ## Steps to Reproduce 23 | 24 | Please provide detailed steps for reproducing the issue. 25 | 26 | 1. step 1 27 | 2. step 2 28 | 3. you get it... 29 | 30 | ## Context 31 | 32 | Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions. 33 | 34 | * Device: 35 | * Operating System: 36 | * Browser and Version: 37 | 38 | ## Failure Logs 39 | 40 | Please include any relevant log snippets or files here. -------------------------------------------------------------------------------- /web/vagrant/nginx/app.conf: -------------------------------------------------------------------------------- 1 | server { 2 | charset utf-8; 3 | client_max_body_size 128M; 4 | sendfile off; 5 | 6 | listen 80; ## listen for ipv4 7 | #listen [::]:80 default_server ipv6only=on; ## listen for ipv6 8 | 9 | server_name yii2basic.test; 10 | root /app/web/; 11 | index index.php; 12 | 13 | access_log /app/vagrant/nginx/log/yii2basic.access.log; 14 | error_log /app/vagrant/nginx/log/yii2basic.error.log; 15 | 16 | location / { 17 | # Redirect everything that isn't a real file to index.php 18 | try_files $uri $uri/ /index.php$is_args$args; 19 | } 20 | 21 | # uncomment to avoid processing of calls to non-existing static files by Yii 22 | #location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ { 23 | # try_files $uri =404; 24 | #} 25 | #error_page 404 /404.html; 26 | 27 | location ~ \.php$ { 28 | include fastcgi_params; 29 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 30 | #fastcgi_pass 127.0.0.1:9000; 31 | fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; 32 | try_files $uri =404; 33 | } 34 | 35 | location ~ /\.(ht|svn|git) { 36 | deny all; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/_badge.scss: -------------------------------------------------------------------------------- 1 | // Base class 2 | // 3 | // Requires one of the contextual, color modifier classes for `color` and 4 | // `background-color`. 5 | 6 | .badge { 7 | display: inline-block; 8 | padding: $badge-padding-y $badge-padding-x; 9 | font-size: $badge-font-size; 10 | font-weight: $badge-font-weight; 11 | line-height: 1; 12 | text-align: center; 13 | white-space: nowrap; 14 | vertical-align: baseline; 15 | @include border-radius($badge-border-radius); 16 | 17 | // Empty badges collapse automatically 18 | &:empty { 19 | display: none; 20 | } 21 | } 22 | 23 | // Quick fix for badges in buttons 24 | .btn .badge { 25 | position: relative; 26 | top: -1px; 27 | } 28 | 29 | // Pill badges 30 | // 31 | // Make them extra rounded with a modifier to replace v3's badges. 32 | 33 | .badge-pill { 34 | padding-right: $badge-pill-padding-x; 35 | padding-left: $badge-pill-padding-x; 36 | @include border-radius($badge-pill-border-radius); 37 | } 38 | 39 | // Colors 40 | // 41 | // Contextual variations (linked badges get darker on :hover). 42 | 43 | @each $color, $value in $theme-colors { 44 | .badge-#{$color} { 45 | @include badge-variant($value); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/_popover.scss: -------------------------------------------------------------------------------- 1 | .popover, .tooltip-inner { 2 | line-height: 1.5em; 3 | background: $white-color; 4 | border: none; 5 | border-radius: $border-radius-base; 6 | @include shadow-8dp(); 7 | color: $popover-color; 8 | } 9 | 10 | 11 | .popover{ 12 | padding: 0; 13 | @include shadow-16dp(); 14 | 15 | &.left, 16 | &.right, 17 | &.top, 18 | &.bottom{ 19 | > .arrow{ 20 | border: none; 21 | } 22 | } 23 | 24 | 25 | &.bs-popover-top, 26 | &.bs-popover-auto[x-placement^="top"], 27 | &.bs-popover-bottom, 28 | &.bs-popover-auto[x-placement^="bottom"], 29 | &.bs-popover-right, 30 | &.bs-popover-auto[x-placement^="right"], 31 | &.bs-popover-left, 32 | &.bs-popover-auto[x-placement^="left"]{ 33 | & .arrow::before{ 34 | border: 0; 35 | } 36 | } 37 | 38 | } 39 | 40 | .popover-header{ 41 | background-color: $white-color; 42 | border: none; 43 | padding: 15px 15px 5px; 44 | font-size: $font-size-h4; 45 | margin: 0; 46 | color: $popover-color; 47 | } 48 | 49 | .popover-body{ 50 | padding: 10px 15px 15px; 51 | line-height: 1.4; 52 | color: $popover-color; 53 | } 54 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/_mixins.scss: -------------------------------------------------------------------------------- 1 | // Toggles 2 | // 3 | // Used in conjunction with global variables to enable certain theme features. 4 | 5 | // Utilities 6 | @import "mixins/breakpoints"; 7 | @import "mixins/hover"; 8 | @import "mixins/image"; 9 | @import "mixins/badge"; 10 | @import "mixins/resize"; 11 | @import "mixins/screen-reader"; 12 | @import "mixins/size"; 13 | @import "mixins/reset-text"; 14 | @import "mixins/text-emphasis"; 15 | @import "mixins/text-hide"; 16 | @import "mixins/text-truncate"; 17 | @import "mixins/visibility"; 18 | 19 | // // Components 20 | @import "mixins/alert"; 21 | @import "mixins/buttons"; 22 | @import "mixins/caret"; 23 | @import "mixins/pagination"; 24 | @import "mixins/lists"; 25 | @import "mixins/list-group"; 26 | @import "mixins/nav-divider"; 27 | @import "mixins/forms"; 28 | @import "mixins/table-row"; 29 | 30 | // // Skins 31 | @import "mixins/background-variant"; 32 | @import "mixins/border-radius"; 33 | @import "mixins/box-shadow"; 34 | @import "mixins/gradients"; 35 | @import "mixins/transition"; 36 | 37 | // // Layout 38 | @import "mixins/clearfix"; 39 | // @import "mixins/navbar-align"; 40 | @import "mixins/grid-framework"; 41 | @import "mixins/grid"; 42 | @import "mixins/float"; 43 | -------------------------------------------------------------------------------- /web/config/test.php: -------------------------------------------------------------------------------- 1 | 'basic-tests', 10 | 'basePath' => dirname(__DIR__), 11 | 'aliases' => [ 12 | '@bower' => '@vendor/bower-asset', 13 | '@npm' => '@vendor/npm-asset', 14 | ], 15 | 'language' => 'en-US', 16 | 'components' => [ 17 | 'db' => $db, 18 | 'mailer' => [ 19 | 'useFileTransport' => true, 20 | ], 21 | 'assetManager' => [ 22 | 'basePath' => __DIR__ . '/../web/assets', 23 | ], 24 | 'urlManager' => [ 25 | 'showScriptName' => true, 26 | ], 27 | 'user' => [ 28 | 'identityClass' => 'app\models\User', 29 | ], 30 | 'request' => [ 31 | 'cookieValidationKey' => 'test', 32 | 'enableCsrfValidation' => false, 33 | // but if you absolutely need it set cookie domain to localhost 34 | /* 35 | 'csrfCookie' => [ 36 | 'domain' => 'localhost', 37 | ], 38 | */ 39 | ], 40 | ], 41 | 'params' => $params, 42 | ]; 43 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/_variables.scss: -------------------------------------------------------------------------------- 1 | @import "variables/colors"; 2 | @import "variables/shadow"; 3 | 4 | @import "variables/bootstrap-material-design-base"; 5 | 6 | // Customized BS variables 7 | @import "variables/custom-forms"; 8 | @import "variables/spacing"; 9 | @import "variables/body"; 10 | @import "variables/brand"; 11 | @import "variables/buttons"; 12 | @import "variables/card"; 13 | @import "variables/code"; 14 | @import "variables/dropdown"; 15 | @import "variables/forms"; 16 | @import "variables/list-group"; 17 | @import "variables/nav"; 18 | @import "variables/pagination"; 19 | @import "variables/state"; 20 | @import "variables/tables"; 21 | @import "variables/tooltip"; 22 | @import "variables/type"; 23 | @import "variables/modals"; 24 | 25 | // import their vars after customization for use below 26 | $enable-flex: true; // fully adopt flexbox layouts 27 | $enable-shadows: true; // enable shadows, set to false to turn off shadows 28 | 29 | // Core Bootstrap Variables 30 | @import "./bootstrap/scss/functions"; 31 | @import "./bootstrap/scss/variables"; 32 | 33 | @import "variables/layout"; 34 | @import "variables/menu"; 35 | @import "variables/drawer"; 36 | @import "variables/snackbar"; 37 | 38 | @import "variables/bootstrap-material-design"; 39 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/_tooltip.scss: -------------------------------------------------------------------------------- 1 | // specs https://material.google.com/components/tooltips.html#tooltips-tooltips-desktop- 2 | 3 | .tooltip-arrow { 4 | display: none; 5 | } 6 | 7 | .tooltip.show{ 8 | opacity: 1; 9 | @include transform-translate-y(0px); 10 | 11 | 12 | } 13 | .tooltip{ 14 | opacity: 0; 15 | transition: opacity, transform .2s ease; 16 | @include transform-translate-y(5px); 17 | font-size: $tooltip-font-size; 18 | 19 | &.bs-tooltip-top, 20 | &.bs-tooltip-auto[x-placement^="top"]{ 21 | & .arrow::before{ 22 | border-top-color: $white-color; 23 | } 24 | } 25 | 26 | &.bs-tooltip-right, 27 | &.bs-tooltip-auto[x-placement^="right"]{ 28 | & .arrow::before{ 29 | border-right-color: $white-color; 30 | } 31 | } 32 | &.bs-tooltip-left, 33 | &.bs-tooltip-auto[x-placement^="left"]{ 34 | & .arrow::before{ 35 | border-left-color: $white-color; 36 | } 37 | } 38 | &.bs-tooltip-bottom, 39 | &.bs-tooltip-auto[x-placement^="bottom"]{ 40 | & .arrow::before{ 41 | border-bottom-color: $white-color; 42 | } 43 | } 44 | } 45 | 46 | .tooltip-inner{ 47 | padding: 10px 15px; 48 | min-width: 130px; 49 | } 50 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/_grid.scss: -------------------------------------------------------------------------------- 1 | // Container widths 2 | // 3 | // Set the container width, and override it for fixed navbars in media queries. 4 | 5 | @if $enable-grid-classes { 6 | .container { 7 | @include make-container(); 8 | @include make-container-max-widths(); 9 | } 10 | } 11 | 12 | // Fluid container 13 | // 14 | // Utilizes the mixin meant for fixed width containers, but with 100% width for 15 | // fluid, full width layouts. 16 | 17 | @if $enable-grid-classes { 18 | .container-fluid { 19 | @include make-container(); 20 | } 21 | } 22 | 23 | // Row 24 | // 25 | // Rows contain and clear the floats of your columns. 26 | 27 | @if $enable-grid-classes { 28 | .row { 29 | @include make-row(); 30 | } 31 | 32 | // Remove the negative margin from default .row, then the horizontal padding 33 | // from all immediate children columns (to prevent runaway style inheritance). 34 | .no-gutters { 35 | margin-right: 0; 36 | margin-left: 0; 37 | 38 | > .col, 39 | > [class*="col-"] { 40 | padding-right: 0; 41 | padding-left: 0; 42 | } 43 | } 44 | } 45 | 46 | // Columns 47 | // 48 | // Common styles for small and large grid columns 49 | 50 | @if $enable-grid-classes { 51 | @include make-grid-columns(); 52 | } 53 | -------------------------------------------------------------------------------- /web/web/demo/demo.css: -------------------------------------------------------------------------------- 1 | .tim-typo { 2 | padding-left: 25%; 3 | margin-bottom: 40px; 4 | position: relative; 5 | width: 100%; 6 | } 7 | 8 | .tim-typo .tim-note { 9 | bottom: 5px; 10 | color: #c0c1c2; 11 | display: block; 12 | font-weight: 400; 13 | font-size: 13px; 14 | line-height: 15px; 15 | left: 0; 16 | margin-left: 20px; 17 | position: absolute; 18 | width: 260px; 19 | } 20 | 21 | /* offline-doc */ 22 | 23 | .offline-doc .navbar.navbar-transparent { 24 | padding-top: 25px; 25 | border-bottom: none; 26 | } 27 | 28 | .offline-doc .navbar.navbar-transparent .navbar-minimize { 29 | display: none; 30 | } 31 | 32 | .offline-doc .navbar.navbar-transparent .navbar-brand, 33 | .offline-doc .navbar.navbar-transparent .collapse .navbar-nav .nav-link { 34 | color: #FFFFFF !important; 35 | } 36 | 37 | .offline-doc .footer { 38 | z-index: 3 !important; 39 | } 40 | 41 | .offline-doc .page-header .container { 42 | z-index: 3; 43 | } 44 | 45 | .offline-doc .page-header:after { 46 | background-color: rgba(0, 0, 0, 0.5); 47 | content: ""; 48 | display: block; 49 | height: 100%; 50 | left: 0; 51 | position: absolute; 52 | top: 0; 53 | width: 100%; 54 | z-index: 2; 55 | } 56 | 57 | #map { 58 | z-index: 2; 59 | height: calc(100vh - 70px); 60 | margin-top: 70px; 61 | } -------------------------------------------------------------------------------- /web/config/console.php: -------------------------------------------------------------------------------- 1 | 'basic-console', 8 | 'basePath' => dirname(__DIR__), 9 | 'bootstrap' => ['log'], 10 | 'controllerNamespace' => 'app\commands', 11 | 'aliases' => [ 12 | '@bower' => '@vendor/bower-asset', 13 | '@npm' => '@vendor/npm-asset', 14 | '@tests' => '@app/tests', 15 | ], 16 | 'components' => [ 17 | 'cache' => [ 18 | 'class' => 'yii\caching\FileCache', 19 | ], 20 | 'log' => [ 21 | 'targets' => [ 22 | [ 23 | 'class' => 'yii\log\FileTarget', 24 | 'levels' => ['error', 'warning'], 25 | ], 26 | ], 27 | ], 28 | 'db' => $db, 29 | ], 30 | 'params' => $params, 31 | /* 32 | 'controllerMap' => [ 33 | 'fixture' => [ // Fixture generation command line. 34 | 'class' => 'yii\faker\FixtureController', 35 | ], 36 | ], 37 | */ 38 | ]; 39 | 40 | if (YII_ENV_DEV) { 41 | // configuration adjustments for 'dev' environment 42 | $config['bootstrap'][] = 'gii'; 43 | $config['modules']['gii'] = [ 44 | 'class' => 'yii\gii\Module', 45 | ]; 46 | } 47 | 48 | return $config; 49 | -------------------------------------------------------------------------------- /web/tests/unit/models/UserTest.php: -------------------------------------------------------------------------------- 1 | username)->equals('admin'); 13 | 14 | expect_not(User::findIdentity(999)); 15 | } 16 | 17 | public function testFindUserByAccessToken() 18 | { 19 | expect_that($user = User::findIdentityByAccessToken('100-token')); 20 | expect($user->username)->equals('admin'); 21 | 22 | expect_not(User::findIdentityByAccessToken('non-existing')); 23 | } 24 | 25 | public function testFindUserByUsername() 26 | { 27 | expect_that($user = User::findByUsername('admin')); 28 | expect_not(User::findByUsername('not-admin')); 29 | } 30 | 31 | /** 32 | * @depends testFindUserByUsername 33 | */ 34 | public function testValidateUser($user) 35 | { 36 | $user = User::findByUsername('admin'); 37 | expect_that($user->validateAuthKey('test100key')); 38 | expect_not($user->validateAuthKey('test102key')); 39 | 40 | expect_that($user->validatePassword('admin')); 41 | expect_not($user->validatePassword('123456')); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/_code.scss: -------------------------------------------------------------------------------- 1 | // Inline and block code styles 2 | code, 3 | kbd, 4 | pre, 5 | samp { 6 | font-family: $font-family-monospace; 7 | } 8 | 9 | // Inline code 10 | code { 11 | font-size: $code-font-size; 12 | color: $code-color; 13 | word-break: break-word; 14 | 15 | // Streamline the style when inside anchors to avoid broken underline and more 16 | a > & { 17 | color: inherit; 18 | } 19 | } 20 | 21 | // User input typically entered via keyboard 22 | kbd { 23 | padding: $kbd-padding-y $kbd-padding-x; 24 | font-size: $kbd-font-size; 25 | color: $kbd-color; 26 | background-color: $kbd-bg; 27 | @include border-radius($border-radius-sm); 28 | @include box-shadow($kbd-box-shadow); 29 | 30 | kbd { 31 | padding: 0; 32 | font-size: 100%; 33 | font-weight: $nested-kbd-font-weight; 34 | @include box-shadow(none); 35 | } 36 | } 37 | 38 | // Blocks of code 39 | pre { 40 | display: block; 41 | font-size: $code-font-size; 42 | color: $pre-color; 43 | 44 | // Account for some code outputs that place code tags in pre tags 45 | code { 46 | font-size: inherit; 47 | color: inherit; 48 | word-break: normal; 49 | } 50 | } 51 | 52 | // Enable scrollable blocks of code 53 | .pre-scrollable { 54 | max-height: $pre-scrollable-max-height; 55 | overflow-y: scroll; 56 | } 57 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/_images.scss: -------------------------------------------------------------------------------- 1 | // Responsive images (ensure images don't scale beyond their parents) 2 | // 3 | // This is purposefully opt-in via an explicit class rather than being the default for all ``s. 4 | // We previously tried the "images are responsive by default" approach in Bootstrap v2, 5 | // and abandoned it in Bootstrap v3 because it breaks lots of third-party widgets (including Google Maps) 6 | // which weren't expecting the images within themselves to be involuntarily resized. 7 | // See also https://github.com/twbs/bootstrap/issues/18178 8 | .img-fluid { 9 | @include img-fluid; 10 | } 11 | 12 | 13 | // Image thumbnails 14 | .img-thumbnail { 15 | padding: $thumbnail-padding; 16 | background-color: $thumbnail-bg; 17 | border: $thumbnail-border-width solid $thumbnail-border-color; 18 | @include border-radius($thumbnail-border-radius); 19 | @include box-shadow($thumbnail-box-shadow); 20 | 21 | // Keep them at most 100% wide 22 | @include img-fluid; 23 | } 24 | 25 | // 26 | // Figures 27 | // 28 | 29 | .figure { 30 | // Ensures the caption's text aligns with the image. 31 | display: inline-block; 32 | } 33 | 34 | .figure-img { 35 | margin-bottom: ($spacer / 2); 36 | line-height: 1; 37 | } 38 | 39 | .figure-caption { 40 | font-size: $figure-caption-font-size; 41 | color: $figure-caption-color; 42 | } 43 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/mixins/_image.scss: -------------------------------------------------------------------------------- 1 | // Image Mixins 2 | // - Responsive image 3 | // - Retina image 4 | 5 | 6 | // Responsive image 7 | // 8 | // Keep images from scaling beyond the width of their parents. 9 | 10 | @mixin img-fluid { 11 | // Part 1: Set a maximum relative to the parent 12 | max-width: 100%; 13 | // Part 2: Override the height to auto, otherwise images will be stretched 14 | // when setting a width and height attribute on the img element. 15 | height: auto; 16 | } 17 | 18 | 19 | // Retina image 20 | // 21 | // Short retina mixin for setting background-image and -size. 22 | 23 | // stylelint-disable indentation, media-query-list-comma-newline-after 24 | @mixin img-retina($file-1x, $file-2x, $width-1x, $height-1x) { 25 | background-image: url($file-1x); 26 | 27 | // Autoprefixer takes care of adding -webkit-min-device-pixel-ratio and -o-min-device-pixel-ratio, 28 | // but doesn't convert dppx=>dpi. 29 | // There's no such thing as unprefixed min-device-pixel-ratio since it's nonstandard. 30 | // Compatibility info: https://caniuse.com/#feat=css-media-resolution 31 | @media only screen and (min-resolution: 192dpi), // IE9-11 don't support dppx 32 | only screen and (min-resolution: 2dppx) { // Standardized 33 | background-image: url($file-2x); 34 | background-size: $width-1x $height-1x; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /web/views/layouts/footer.php: -------------------------------------------------------------------------------- 1 | 6 | * @link https://www.coderseden.com 7 | * @copyright 2020 Material Dashboard Yii2 (https://www.coderseden.com) 8 | * @license MIT - https://www.coderseden.com 9 | * @since 1.0 10 | */ 11 | ?> 12 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/_alert.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Base styles 3 | // 4 | 5 | .alert { 6 | position: relative; 7 | padding: $alert-padding-y $alert-padding-x; 8 | margin-bottom: $alert-margin-bottom; 9 | border: $alert-border-width solid transparent; 10 | @include border-radius($alert-border-radius); 11 | } 12 | 13 | // Headings for larger alerts 14 | .alert-heading { 15 | // Specified to prevent conflicts of changing $headings-color 16 | color: inherit; 17 | } 18 | 19 | // Provide class for links that match alerts 20 | .alert-link { 21 | font-weight: $alert-link-font-weight; 22 | } 23 | 24 | 25 | // Dismissible alerts 26 | // 27 | // Expand the right padding and account for the close button's positioning. 28 | 29 | .alert-dismissible { 30 | padding-right: ($close-font-size + $alert-padding-x * 2); 31 | 32 | // Adjust close link position 33 | .close { 34 | position: absolute; 35 | top: 0; 36 | right: 0; 37 | padding: $alert-padding-y $alert-padding-x; 38 | color: inherit; 39 | } 40 | } 41 | 42 | 43 | // Alternate styles 44 | // 45 | // Generate contextual modifier classes for colorizing the alert. 46 | 47 | @each $color, $value in $theme-colors { 48 | .alert-#{$color} { 49 | @include alert-variant(theme-color-level($color, $alert-bg-level), theme-color-level($color, $alert-border-level), theme-color-level($color, $alert-color-level)); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /web/tests/unit/models/LoginFormTest.php: -------------------------------------------------------------------------------- 1 | user->logout(); 14 | } 15 | 16 | public function testLoginNoUser() 17 | { 18 | $this->model = new LoginForm([ 19 | 'username' => 'not_existing_username', 20 | 'password' => 'not_existing_password', 21 | ]); 22 | 23 | expect_not($this->model->login()); 24 | expect_that(\Yii::$app->user->isGuest); 25 | } 26 | 27 | public function testLoginWrongPassword() 28 | { 29 | $this->model = new LoginForm([ 30 | 'username' => 'demo', 31 | 'password' => 'wrong_password', 32 | ]); 33 | 34 | expect_not($this->model->login()); 35 | expect_that(\Yii::$app->user->isGuest); 36 | expect($this->model->errors)->hasKey('password'); 37 | } 38 | 39 | public function testLoginCorrect() 40 | { 41 | $this->model = new LoginForm([ 42 | 'username' => 'demo', 43 | 'password' => 'demo', 44 | ]); 45 | 46 | expect_that($this->model->login()); 47 | expect_not(\Yii::$app->user->isGuest); 48 | expect($this->model->errors)->hasntKey('password'); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/_breadcrumb.scss: -------------------------------------------------------------------------------- 1 | .breadcrumb { 2 | display: flex; 3 | flex-wrap: wrap; 4 | padding: $breadcrumb-padding-y $breadcrumb-padding-x; 5 | margin-bottom: $breadcrumb-margin-bottom; 6 | list-style: none; 7 | background-color: $breadcrumb-bg; 8 | @include border-radius($border-radius); 9 | } 10 | 11 | .breadcrumb-item { 12 | // The separator between breadcrumbs (by default, a forward-slash: "/") 13 | + .breadcrumb-item::before { 14 | display: inline-block; // Suppress underlining of the separator in modern browsers 15 | padding-right: $breadcrumb-item-padding; 16 | padding-left: $breadcrumb-item-padding; 17 | color: $breadcrumb-divider-color; 18 | content: "#{$breadcrumb-divider}"; 19 | } 20 | 21 | // IE9-11 hack to properly handle hyperlink underlines for breadcrumbs built 22 | // without `
    `s. The `::before` pseudo-element generates an element 23 | // *within* the .breadcrumb-item and thereby inherits the `text-decoration`. 24 | // 25 | // To trick IE into suppressing the underline, we give the pseudo-element an 26 | // underline and then immediately remove it. 27 | + .breadcrumb-item:hover::before { 28 | text-decoration: underline; 29 | } 30 | // stylelint-disable-next-line no-duplicate-selectors 31 | + .breadcrumb-item:hover::before { 32 | text-decoration: none; 33 | } 34 | 35 | &.active { 36 | color: $breadcrumb-active-color; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /web/views/icons/index.php: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    4 |
    5 |
    6 |

    Material Design Icons

    7 |

    Handcrafted by our friends from 8 | Google 9 |

    10 |
    11 |
    12 |
    13 |
    14 |
    15 | 18 |
    19 |
    20 |
    The icons are visible on Desktop mode inside an iframe. Since the iframe is not working on Mobile and Tablets please visit the icons on their original page on Google. Check the 21 | Material Icons 22 |
    23 |
    24 |
    25 |
    26 |
    27 |
    28 |
    29 |
    30 |
    -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/mixins/_navs.scss: -------------------------------------------------------------------------------- 1 | @mixin bmd-tabs-color($color, $active-color, $active-border, $disabled-link-color, $disabled-link-hover-color) { 2 | .nav-link { 3 | color: $color; 4 | 5 | &.active { 6 | color: $active-color; 7 | border-color: $active-border; 8 | @include hover-focus { 9 | border-color: $active-border; 10 | } 11 | } 12 | 13 | // Disabled state lightens text and removes hover/tab effects 14 | &.disabled { 15 | color: $disabled-link-color; 16 | 17 | @include plain-hover-focus { 18 | color: $disabled-link-hover-color; 19 | } 20 | } 21 | } 22 | } 23 | 24 | @mixin set-wizard-color($color) { 25 | 26 | .moving-tab{ 27 | background-color: $color; 28 | @include shadow-big-color($color); 29 | } 30 | 31 | .picture{ 32 | &:hover{ 33 | border-color: $color; 34 | } 35 | } 36 | 37 | .choice{ 38 | &:hover, 39 | &.active{ 40 | .icon{ 41 | border-color: $color; 42 | color: $color; 43 | } 44 | } 45 | } 46 | 47 | 48 | .checkbox input[type=checkbox]:checked + .checkbox-material{ 49 | .check{ 50 | background-color: $color; 51 | } 52 | } 53 | 54 | .radio input[type=radio]:checked ~ .check { 55 | background-color: $color; 56 | } 57 | 58 | .radio input[type=radio]:checked ~ .circle { 59 | border-color: $color; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/mixins/_sidebar-color.scss: -------------------------------------------------------------------------------- 1 | @mixin sidebar-background-color($background-color, $font-color){ 2 | .nav{ 3 | .nav-item{ 4 | .nav-link{ 5 | color: $font-color; 6 | } 7 | i{ 8 | color: rgba($font-color, .8); 9 | } 10 | 11 | &.active, 12 | &:hover{ 13 | [data-toggle="collapse"]{ 14 | color: $font-color; 15 | i{ 16 | color: rgba($font-color, .8); 17 | } 18 | } 19 | } 20 | } 21 | } 22 | .user{ 23 | a{ 24 | color: $font-color; 25 | } 26 | } 27 | .simple-text{ 28 | color: $font-color; 29 | } 30 | .sidebar-background:after{ 31 | background: $background-color; 32 | opacity: .8; 33 | } 34 | } 35 | 36 | @mixin sidebar-active-color($font-color){ 37 | .nav{ 38 | .nav-item{ 39 | &.active > a:not([data-toggle="collapse"]){ 40 | color: $font-color; 41 | opacity: 1; 42 | @include shadow-big-color($font-color); 43 | 44 | i{ 45 | color: rgba($font-color, .8); 46 | } 47 | } 48 | } 49 | } 50 | } 51 | 52 | @mixin set-background-color-button($color){ 53 | 54 | li.active > a{ 55 | background-color: $color; 56 | @include shadow-big-color($color); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/variables/_modals.scss: -------------------------------------------------------------------------------- 1 | // Modals 2 | $modal-content-xs-box-shadow: $bmd-shadow-24dp !default; 3 | 4 | // Padding applied to the modal body 5 | //$modal-inner-padding: 15px !default; 6 | // 7 | //$modal-title-padding: 15px !default; 8 | //$modal-title-line-height: $line-height-base !default; 9 | // 10 | //$modal-content-bg: #fff !default; 11 | //$modal-content-border-color: rgba(0,0,0,.2) !default; 12 | // 13 | //$modal-backdrop-bg: #000 !default; 14 | $modal-backdrop-opacity: .26 !default; // .5 15 | //$modal-header-border-color: #e5e5e5 !default; 16 | //$modal-footer-border-color: $modal-header-border-color !default; 17 | // 18 | //$modal-lg: 900px !default; 19 | //$modal-md: 600px !default; 20 | //$modal-sm: 300px !default; 21 | 22 | $transition-ease-in: ease-in !default; 23 | $transition-ease-out: ease-out !default; 24 | $ultra-fast-transition-time: 60ms !default; 25 | $navbar-padding-a: 10px 15px; 26 | $padding-zero: 0px !default; 27 | $sidebar-width: calc(100% - 260px) !default; 28 | $sidebar-mini-width: calc(100% - 80px) !default; 29 | $topbar-back: topbar-back !default; 30 | $bottombar-back: bottombar-back !default; 31 | $topbar-x: topbar-x !default; 32 | $bottombar-x: bottombar-x !default; 33 | $margin-bottom: 0 0 10px 0 !default; 34 | $margin-base-vertical: 15px !default; 35 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/utilities/_text.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable declaration-no-important 2 | 3 | // 4 | // Text 5 | // 6 | 7 | // Alignment 8 | 9 | .text-justify { text-align: justify !important; } 10 | .text-nowrap { white-space: nowrap !important; } 11 | .text-truncate { @include text-truncate; } 12 | 13 | // Responsive alignment 14 | 15 | @each $breakpoint in map-keys($grid-breakpoints) { 16 | @include media-breakpoint-up($breakpoint) { 17 | $infix: breakpoint-infix($breakpoint, $grid-breakpoints); 18 | 19 | .text#{$infix}-left { text-align: left !important; } 20 | .text#{$infix}-right { text-align: right !important; } 21 | .text#{$infix}-center { text-align: center !important; } 22 | } 23 | } 24 | 25 | // Transformation 26 | 27 | .text-lowercase { text-transform: lowercase !important; } 28 | .text-uppercase { text-transform: uppercase !important; } 29 | .text-capitalize { text-transform: capitalize !important; } 30 | 31 | // Weight and italics 32 | 33 | .font-weight-light { font-weight: $font-weight-light !important; } 34 | .font-weight-normal { font-weight: $font-weight-normal !important; } 35 | .font-weight-bold { font-weight: $font-weight-bold !important; } 36 | .font-italic { font-style: italic !important; } 37 | 38 | // Contextual colors 39 | 40 | .text-white { color: #fff !important; } 41 | 42 | @each $color, $value in $theme-colors { 43 | @include text-emphasis-variant(".text-#{$color}", $value); 44 | } 45 | 46 | .text-muted { color: $text-muted !important; } 47 | 48 | // Misc 49 | 50 | .text-hide { 51 | @include text-hide(); 52 | } 53 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/utilities/_display.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable declaration-no-important 2 | 3 | // 4 | // Utilities for common `display` values 5 | // 6 | 7 | @each $breakpoint in map-keys($grid-breakpoints) { 8 | @include media-breakpoint-up($breakpoint) { 9 | $infix: breakpoint-infix($breakpoint, $grid-breakpoints); 10 | 11 | .d#{$infix}-none { display: none !important; } 12 | .d#{$infix}-inline { display: inline !important; } 13 | .d#{$infix}-inline-block { display: inline-block !important; } 14 | .d#{$infix}-block { display: block !important; } 15 | .d#{$infix}-table { display: table !important; } 16 | .d#{$infix}-table-row { display: table-row !important; } 17 | .d#{$infix}-table-cell { display: table-cell !important; } 18 | .d#{$infix}-flex { display: flex !important; } 19 | .d#{$infix}-inline-flex { display: inline-flex !important; } 20 | } 21 | } 22 | 23 | 24 | // 25 | // Utilities for toggling `display` in print 26 | // 27 | 28 | @media print { 29 | .d-print-none { display: none !important; } 30 | .d-print-inline { display: inline !important; } 31 | .d-print-inline-block { display: inline-block !important; } 32 | .d-print-block { display: block !important; } 33 | .d-print-table { display: table !important; } 34 | .d-print-table-row { display: table-row !important; } 35 | .d-print-table-cell { display: table-cell !important; } 36 | .d-print-flex { display: flex !important; } 37 | .d-print-inline-flex { display: inline-flex !important; } 38 | } 39 | -------------------------------------------------------------------------------- /web/LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © 2008 by Yii Software LLC (http://www.yiisoft.com) 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in 12 | the documentation and/or other materials provided with the 13 | distribution. 14 | * Neither the name of Yii Software LLC nor the names of its 15 | contributors may be used to endorse or promote products derived 16 | from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 28 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 | POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/variables/_bootstrap-material-design-base.scss: -------------------------------------------------------------------------------- 1 | $gray-lighter: rgba($black, 0.12) !default; 2 | $gray-light: #999 !default; 3 | $gray-alpha: .54 !default; 4 | $gray: #555 !default; // spec color 5 | $gray-dark: rgba($black, 0.87) !default; // used for text color - others use grey-600 which is considerably lighter 6 | 7 | $bmd-font-weight-base: 400; 8 | 9 | // wondering if any of these could still be refactored out, but are definitely in use. 10 | $bmd-inverse: rgba($white, 1) !default; 11 | $bmd-inverse-light: rgba($white, 0.84) !default; 12 | $bmd-inverse-lighter: rgba($white, 0.54) !default; 13 | 14 | $bmd-label-color: $gray-color !default; 15 | $bmd-label-color-inner-focus: $gray !default; // e.g. radio label or text-muted not a control-label which is primary 16 | 17 | $border-radius-base: 3px !default; 18 | $border-radius-small: 2px !default; 19 | $border-radius-large: 6px !default; 20 | $border-radius-huge: 10px !default; 21 | $border-radius-label: 12px !default; 22 | $border-radius-extreme: 30px !default; 23 | 24 | // Typography elements 25 | $mdb-font-family: 'Roboto', 'Helvetica', 'Arial', sans-serif !default; 26 | $mdb-text-color-light: $white !default; 27 | $mdb-text-color-light-hex: $white !default; // for contrast function in inverse 28 | $mdb-text-color-primary: unquote("rgba(#{$rgb-black}, 0.87)") !default; 29 | $mdb-text-color-primary-hex: $black !default; // for contrast function in inverse 30 | $icon-color: rgba(0,0,0,0.5) !default; 31 | 32 | $mdb-label-color: unquote("rgba(#{$rgb-black}, 0.26)") !default; 33 | $mdb-label-color-toggle-focus: unquote("rgba(#{$rgb-black}, .54)") !default; 34 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/utilities/_spacing.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable declaration-no-important 2 | 3 | // Margin and Padding 4 | 5 | @each $breakpoint in map-keys($grid-breakpoints) { 6 | @include media-breakpoint-up($breakpoint) { 7 | $infix: breakpoint-infix($breakpoint, $grid-breakpoints); 8 | 9 | @each $prop, $abbrev in (margin: m, padding: p) { 10 | @each $size, $length in $spacers { 11 | 12 | .#{$abbrev}#{$infix}-#{$size} { #{$prop}: $length !important; } 13 | .#{$abbrev}t#{$infix}-#{$size}, 14 | .#{$abbrev}y#{$infix}-#{$size} { 15 | #{$prop}-top: $length !important; 16 | } 17 | .#{$abbrev}r#{$infix}-#{$size}, 18 | .#{$abbrev}x#{$infix}-#{$size} { 19 | #{$prop}-right: $length !important; 20 | } 21 | .#{$abbrev}b#{$infix}-#{$size}, 22 | .#{$abbrev}y#{$infix}-#{$size} { 23 | #{$prop}-bottom: $length !important; 24 | } 25 | .#{$abbrev}l#{$infix}-#{$size}, 26 | .#{$abbrev}x#{$infix}-#{$size} { 27 | #{$prop}-left: $length !important; 28 | } 29 | } 30 | } 31 | 32 | // Some special margin utils 33 | .m#{$infix}-auto { margin: auto !important; } 34 | .mt#{$infix}-auto, 35 | .my#{$infix}-auto { 36 | margin-top: auto !important; 37 | } 38 | .mr#{$infix}-auto, 39 | .mx#{$infix}-auto { 40 | margin-right: auto !important; 41 | } 42 | .mb#{$infix}-auto, 43 | .my#{$infix}-auto { 44 | margin-bottom: auto !important; 45 | } 46 | .ml#{$infix}-auto, 47 | .mx#{$infix}-auto { 48 | margin-left: auto !important; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | # 2 | # @package Material Dashboard Yii2 3 | # @author CodersEden 4 | # @link https://www.coderseden.com 5 | # @copyright 2020 Material Dashboard Yii2 (https://www.coderseden.com) 6 | # @license MIT - https://www.coderseden.com 7 | # @since 1.0 8 | material-dashboard-mysql: 9 | image: mysql:5.7 10 | container_name: material-dashboard-mysql 11 | environment: 12 | - MYSQL_ROOT_PASSWORD=material-dashboard 13 | - MYSQL_DATABASE=material-dashboard 14 | - MYSQL_USER=material-dashboard 15 | - MYSQL_PASSWORD=material-dashboard 16 | - MYSQL_PORT=3306 17 | - MYSQL_HOST=localhost 18 | 19 | material-dashboard-webserver: 20 | image: phpdockerio/nginx:latest 21 | container_name: material-dashboard-webserver 22 | volumes: 23 | - ../web:/var/www/material-dashboard/web 24 | - ./ssl:/etc/nginx/ssl 25 | - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf 26 | ports: 27 | - "80:80" 28 | - "443:443" 29 | links: 30 | - material-dashboard-php-fpm 31 | 32 | material-dashboard-php-fpm: 33 | build: . 34 | dockerfile: php-fpm/Dockerfile 35 | container_name: material-dashboard-php-fpm 36 | volumes: 37 | - ../web:/var/www/material-dashboard/web 38 | - ./php-fpm/php-ini-overrides.ini:/etc/php/7.2/fpm/conf.d/99-overrides.ini 39 | links: 40 | - material-dashboard-mysql 41 | environment: 42 | YII_ENV_DOCKER: 1 43 | 44 | material-dashboard-phpmyadmin: 45 | image: phpmyadmin/phpmyadmin 46 | container_name: material-dashboard-phpmyadmin 47 | environment: 48 | - PMA_ARBITRARY=1 49 | - PMA_HOST=material-dashboard-mysql 50 | restart: always 51 | ports: 52 | - 81:80 53 | links: 54 | - material-dashboard-mysql 55 | -------------------------------------------------------------------------------- /docker/ssl/material-dashboard.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEkDCCAvigAwIBAgIQSeSCKswCizkglrNSYLOgaTANBgkqhkiG9w0BAQsFADCB 3 | izEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMTAwLgYDVQQLDCdBYnVk 4 | ZUBNYWNCb29rLVByby5sb2NhbCAoQWJ1ZGUgQmF5YXNzaSkxNzA1BgNVBAMMLm1r 5 | Y2VydCBBYnVkZUBNYWNCb29rLVByby5sb2NhbCAoQWJ1ZGUgQmF5YXNzaSkwHhcN 6 | MTkwNjAxMDAwMDAwWhcNMzAwMjE2MjE1OTM0WjBhMScwJQYDVQQKEx5ta2NlcnQg 7 | ZGV2ZWxvcG1lbnQgY2VydGlmaWNhdGUxNjA0BgNVBAsMLUFidWRlQDE5Mi0xNjgt 8 | MC0xMDYucmRzbmV0LnJvIChBYnVkZSBCYXlhc3NpKTCCASIwDQYJKoZIhvcNAQEB 9 | BQADggEPADCCAQoCggEBAOWL0H3eRb+pa3SxQyxPkCQlQt0C4Car/DGzZnjwQrFG 10 | hX/57GJyhjwdU4c77+I80MKm4UpgKlArVFZfDAjj1Om70KltZdxSEr8UZJ0E/VJS 11 | 0jz31fzHzi3zpml/IoKx+gGBEL5lQ52Zu3AiwUzaPLzOdZfOKqolCMZAszfrlmnE 12 | fGBciH5S+Yd2yYqnEHMZaa0sDBYUh2DX0+lhm7u/vTcA5JW8KsZYTDJncr5Cscc7 13 | Qg32f9n1jNvEIm0tUtHpNWdbhMM670Kve0yYpJwj5nurL8WB6jt96AfaOr4MMs58 14 | grAXtEXNisDkQHufxOlW9K/LBXmHLJ4QBiaZmGgwChUCAwEAAaOBmDCBlTAOBgNV 15 | HQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAf 16 | BgNVHSMEGDAWgBQdb4oaO/UnpbYW3kKGG0x8pSTuNTA/BgNVHREEODA2ghdtYXRl 17 | cmlhbC1kYXNoYm9hcmQudGVzdIIbd3d3Lm1hdGVyaWFsLWRhc2hib2FyZC50ZXN0 18 | MA0GCSqGSIb3DQEBCwUAA4IBgQANTVguc/jYLob1aFiuh8vzenzI7Xbon+fv/GtS 19 | psALX6/q0G778Q3S4NGV48W11aFEqwPNwNkU7Q8nxIcm/JLegeYWQD5tfhVKZ81v 20 | MfhIBr/Gk4dcUc/bwatx7at0EZTDXErVEoDlbaYnIVBDtu9GBRd/DLeCi66jjsjL 21 | 1To+8ZOh3AjbFO6bQ+bfUc5llTzTQyR0ven9TQb7y4msmn7Zotm8bJaXSktFqOzU 22 | jPE7Kyq1ux25oLwahKOTrMG6j4AE2/npZ/91GmiRvV7deK3Bag+4lfdHVM1uJgUC 23 | r/7xILWt4aM34DhrrMQ0hckWzDmkHRM7uLSJyL8DdA8d7c91swqE6LxgpgbrJeom 24 | C5DJ0sVV+zrZ+n7KN8qALscrfCseKrVzVD+t6RUaOZSSIJTM88gZWSEiNvWhu23u 25 | wUkav9Gtxb/vT2ywKIyEqtCdtYzs+uPzddNCUHMZy0TbKEw7GKKrP7/zAkJHzuaA 26 | QJJu+muGYzaEHl4ySryvfDzTEiw= 27 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/mixins/_caret.scss: -------------------------------------------------------------------------------- 1 | @mixin caret-down { 2 | border-top: $caret-width solid; 3 | border-right: $caret-width solid transparent; 4 | border-bottom: 0; 5 | border-left: $caret-width solid transparent; 6 | } 7 | 8 | @mixin caret-up { 9 | border-top: 0; 10 | border-right: $caret-width solid transparent; 11 | border-bottom: $caret-width solid; 12 | border-left: $caret-width solid transparent; 13 | } 14 | 15 | @mixin caret-right { 16 | border-top: $caret-width solid transparent; 17 | border-bottom: $caret-width solid transparent; 18 | border-left: $caret-width solid; 19 | } 20 | 21 | @mixin caret-left { 22 | border-top: $caret-width solid transparent; 23 | border-right: $caret-width solid; 24 | border-bottom: $caret-width solid transparent; 25 | } 26 | 27 | @mixin caret($direction: down) { 28 | @if $enable-caret { 29 | &::after { 30 | display: inline-block; 31 | width: 0; 32 | height: 0; 33 | margin-left: $caret-width * .85; 34 | vertical-align: $caret-width * .85; 35 | content: ""; 36 | @if $direction == down { 37 | @include caret-down; 38 | } @else if $direction == up { 39 | @include caret-up; 40 | } @else if $direction == right { 41 | @include caret-right; 42 | } 43 | } 44 | 45 | @if $direction == left { 46 | &::after { 47 | display: none; 48 | } 49 | 50 | &::before { 51 | display: inline-block; 52 | width: 0; 53 | height: 0; 54 | margin-right: $caret-width * .85; 55 | vertical-align: $caret-width * .85; 56 | content: ""; 57 | @include caret-left; 58 | } 59 | } 60 | 61 | &:empty::after { 62 | margin-left: 0; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /docker/nginx/nginx.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name material-dashboard.test; 4 | return 301 https://$server_name$request_uri; 5 | } 6 | # 7 | # @package Material Dashboard Yii2 8 | # @author CodersEden 9 | # @link https://www.coderseden.com 10 | # @copyright 2020 Material Dashboard Yii2 (https://www.coderseden.com) 11 | # @license MIT - https://www.coderseden.com 12 | # @since 1.0 13 | server { 14 | listen 443 ssl; 15 | 16 | ssl on; 17 | ssl_certificate /etc/nginx/ssl/material-dashboard.crt; 18 | ssl_certificate_key /etc/nginx/ssl/material-dashboard.key; 19 | 20 | # max upload 21 | client_max_body_size 108M; 22 | 23 | # keep utf-8 24 | charset UTF-8; 25 | 26 | # http://serverfault.com/questions/269420/disable-caching-when-serving-static-files-with-nginx-for-development 27 | sendfile off; 28 | 29 | access_log /var/log/nginx/material-dashboard.access.log; 30 | 31 | root /var/www/material-dashboard/web/web; 32 | index index.php; 33 | 34 | 35 | location / { 36 | if (!-e $request_filename){ 37 | rewrite ^(/)?admin/.*$ /admin/index.php; 38 | } 39 | if (!-e $request_filename){ 40 | rewrite ^(.*)$ /index.php; 41 | } 42 | index index.html index.htm index.php; 43 | } 44 | 45 | location ~ \.php$ { 46 | fastcgi_pass material-dashboard-php-fpm:9000; 47 | fastcgi_index index.php; 48 | fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 49 | fastcgi_param PHP_VALUE "error_log=/var/log/nginx/yii2_php_errors.log"; 50 | fastcgi_buffers 16 16k; 51 | fastcgi_buffer_size 32k; 52 | fastcgi_intercept_errors on; 53 | include fastcgi_params; 54 | } 55 | } -------------------------------------------------------------------------------- /web/tests/unit/models/ContactFormTest.php: -------------------------------------------------------------------------------- 1 | model = $this->getMockBuilder('app\models\ContactForm') 20 | ->setMethods(['validate']) 21 | ->getMock(); 22 | 23 | $this->model->expects($this->once()) 24 | ->method('validate') 25 | ->willReturn(true); 26 | 27 | $this->model->attributes = [ 28 | 'name' => 'Tester', 29 | 'email' => 'tester@example.com', 30 | 'subject' => 'very important letter subject', 31 | 'body' => 'body of current message', 32 | ]; 33 | 34 | expect_that($this->model->contact('admin@example.com')); 35 | 36 | // using Yii2 module actions to check email was sent 37 | $this->tester->seeEmailIsSent(); 38 | 39 | /** @var MessageInterface $emailMessage */ 40 | $emailMessage = $this->tester->grabLastSentEmail(); 41 | expect('valid email is sent', $emailMessage)->isInstanceOf('yii\mail\MessageInterface'); 42 | expect($emailMessage->getTo())->hasKey('admin@example.com'); 43 | expect($emailMessage->getFrom())->hasKey('noreply@example.com'); 44 | expect($emailMessage->getReplyTo())->hasKey('tester@example.com'); 45 | expect($emailMessage->getSubject())->equals('very important letter subject'); 46 | expect($emailMessage->toString())->stringContainsString('body of current message'); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /docker/ssl/material-dashboard.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDli9B93kW/qWt0 3 | sUMsT5AkJULdAuAmq/wxs2Z48EKxRoV/+exicoY8HVOHO+/iPNDCpuFKYCpQK1RW 4 | XwwI49Tpu9CpbWXcUhK/FGSdBP1SUtI899X8x84t86ZpfyKCsfoBgRC+ZUOdmbtw 5 | IsFM2jy8znWXziqqJQjGQLM365ZpxHxgXIh+UvmHdsmKpxBzGWmtLAwWFIdg19Pp 6 | YZu7v703AOSVvCrGWEwyZ3K+QrHHO0IN9n/Z9YzbxCJtLVLR6TVnW4TDOu9Cr3tM 7 | mKScI+Z7qy/Fgeo7fegH2jq+DDLOfIKwF7RFzYrA5EB7n8TpVvSvywV5hyyeEAYm 8 | mZhoMAoVAgMBAAECggEBAM6Y9RCkQjCLonxHosa54Wi25KQYl3gW6QguiHcm/0+g 9 | wjz5yuicXPa0Cl638mK0C8x1+GVBgjPfm6uVJjbGH/YypU4oeTo/4EF8cEXmnL1A 10 | b5qSEVXO22H+XnOrCnuJBhPefxxt9dpd6Ba4ITQzY+EnDS2RUFMMvAX7a5JUBm+v 11 | xP8bjN7kDI33WB+U++cL1DYUa2nTFy9MueGDzeZnZ+zZccbgftTsUT47JhW4FfHB 12 | xg+PGMjWoQxsPP6CHo97WPzVghVHphdFBLSt8NNedZ6Mqmx8mTjqBs4JA8XHZMaB 13 | N1SUMY6qDSy49j46yKjEC9DR8PkKzqQfTfS9dnkJoM0CgYEA+2ewkiHcvFea6wcb 14 | Q0iV/33tWG7/EsJWYo5d6BUwwwnQxiG9Yh4FLB/p13GStzuk20w/0wPynfqXrZwl 15 | j6BFKCz4m3X1U6/US2nALFR4xjvw81k3UeFvdqcgxyeBicE6londMOlABzpa2JyN 16 | hQDWP1Hlp1qCOfltKDkJHnblF/sCgYEA6b3ZITV8/YE6LK7329pQZVz00X55zF2G 17 | uDTWCbR3l2h2mEuYtwWdPX7h8rSDuoeYiZoP1h1lOTq4rsVTGguMXIeDC7KswuLy 18 | mzRqKhMYg3jR8RL46V/n4Mq7WDmGMScq+QkzJbzg3IqsGKEWB8RNqqFG4JWQvk5q 19 | kSSagEJxeS8CgYB9Gif/T+JrxpxMgAjM/n3F2YAWFYXQa+xYtsd8Ca9uHqBJN9jp 20 | zk58mpTepKGBlKiAh/zqoHhGrMB1n9IBGpvPVjGQCq69qi1WKZV7eb1vx7wrHCYv 21 | FKNGw/vHnp0TU5g3+PqcsDUwY5V5XM3/dV8nuzUwhhVvi/MJpPgotLljqQKBgQDd 22 | pNG9RNw2AxFoB64vAvCTfbcE5HqYiONTz35bC48PutYiiiTRAHjfNG8LV5NGEIhb 23 | iwSTU6KFxyITUDgCDYtWvoVMVWyvDMdi1ywIo7zuBmaFxCjWG8Rki7lk6n9OIscE 24 | CW4/zcAoQTL5095xFPtU3sO3+PudCfzRjzUWhGrXrwKBgC7unPGQGKQBlMQRP23k 25 | apb2x47VNUxMPUzFKV5e5ExE725jnTOwZS8tgVzrrdvY1SrNcZVN+WNESjUEE7Te 26 | jIxarus+PNDob7be0xk7eMheVb4kM5OCzzeMK5xXAUh0n03nDXi0vgmU5tsQ95GU 27 | yGG0XWew8Jp96ns1PdGBlt/d 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/utilities/_borders.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable declaration-no-important 2 | 3 | // 4 | // Border 5 | // 6 | 7 | .border { border: $border-width solid $border-color !important; } 8 | .border-top { border-top: $border-width solid $border-color !important; } 9 | .border-right { border-right: $border-width solid $border-color !important; } 10 | .border-bottom { border-bottom: $border-width solid $border-color !important; } 11 | .border-left { border-left: $border-width solid $border-color !important; } 12 | 13 | .border-0 { border: 0 !important; } 14 | .border-top-0 { border-top: 0 !important; } 15 | .border-right-0 { border-right: 0 !important; } 16 | .border-bottom-0 { border-bottom: 0 !important; } 17 | .border-left-0 { border-left: 0 !important; } 18 | 19 | @each $color, $value in $theme-colors { 20 | .border-#{$color} { 21 | border-color: $value !important; 22 | } 23 | } 24 | 25 | .border-white { 26 | border-color: $white !important; 27 | } 28 | 29 | // 30 | // Border-radius 31 | // 32 | 33 | .rounded { 34 | border-radius: $border-radius !important; 35 | } 36 | .rounded-top { 37 | border-top-left-radius: $border-radius !important; 38 | border-top-right-radius: $border-radius !important; 39 | } 40 | .rounded-right { 41 | border-top-right-radius: $border-radius !important; 42 | border-bottom-right-radius: $border-radius !important; 43 | } 44 | .rounded-bottom { 45 | border-bottom-right-radius: $border-radius !important; 46 | border-bottom-left-radius: $border-radius !important; 47 | } 48 | .rounded-left { 49 | border-top-left-radius: $border-radius !important; 50 | border-bottom-left-radius: $border-radius !important; 51 | } 52 | 53 | .rounded-circle { 54 | border-radius: 50% !important; 55 | } 56 | 57 | .rounded-0 { 58 | border-radius: 0 !important; 59 | } 60 | -------------------------------------------------------------------------------- /web/tests/functional/LoginFormCest.php: -------------------------------------------------------------------------------- 1 | amOnRoute('site/login'); 8 | } 9 | 10 | public function openLoginPage(\FunctionalTester $I) 11 | { 12 | $I->see('Login', 'h1'); 13 | 14 | } 15 | 16 | // demonstrates `amLoggedInAs` method 17 | public function internalLoginById(\FunctionalTester $I) 18 | { 19 | $I->amLoggedInAs(100); 20 | $I->amOnPage('/'); 21 | $I->see('Logout (admin)'); 22 | } 23 | 24 | // demonstrates `amLoggedInAs` method 25 | public function internalLoginByInstance(\FunctionalTester $I) 26 | { 27 | $I->amLoggedInAs(\app\models\User::findByUsername('admin')); 28 | $I->amOnPage('/'); 29 | $I->see('Logout (admin)'); 30 | } 31 | 32 | public function loginWithEmptyCredentials(\FunctionalTester $I) 33 | { 34 | $I->submitForm('#login-form', []); 35 | $I->expectTo('see validations errors'); 36 | $I->see('Username cannot be blank.'); 37 | $I->see('Password cannot be blank.'); 38 | } 39 | 40 | public function loginWithWrongCredentials(\FunctionalTester $I) 41 | { 42 | $I->submitForm('#login-form', [ 43 | 'LoginForm[username]' => 'admin', 44 | 'LoginForm[password]' => 'wrong', 45 | ]); 46 | $I->expectTo('see validations errors'); 47 | $I->see('Incorrect username or password.'); 48 | } 49 | 50 | public function loginSuccessfully(\FunctionalTester $I) 51 | { 52 | $I->submitForm('#login-form', [ 53 | 'LoginForm[username]' => 'admin', 54 | 'LoginForm[password]' => 'admin', 55 | ]); 56 | $I->see('Logout (admin)'); 57 | $I->dontSeeElement('form#login-form'); 58 | } 59 | } -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/variables/_shadow.scss: -------------------------------------------------------------------------------- 1 | // Shadows (originally from mdl http://www.getmdl.io/) 2 | $bmd-shadow-umbra-opacity: 0.2 !default; 3 | $bmd-shadow-penumbra-opacity: 0.14 !default; 4 | $bmd-shadow-ambient-opacity: 0.12 !default; 5 | 6 | // Declare the following for reuse with both mixins and the bootstrap variables 7 | $bmd-shadow-focus: 0 0 8px rgba($black, .18), 0 8px 16px rgba($black, .36); 8 | 9 | $bmd-shadow-2dp: 0 2px 2px 0 rgba($black, $bmd-shadow-penumbra-opacity), 10 | 0 3px 1px -2px rgba($black, $bmd-shadow-umbra-opacity), 11 | 0 1px 5px 0 rgba($black, $bmd-shadow-ambient-opacity); 12 | 13 | $bmd-shadow-3dp: 0 3px 4px 0 rgba($black, $bmd-shadow-penumbra-opacity), 14 | 0 3px 3px -2px rgba($black, $bmd-shadow-umbra-opacity), 15 | 0 1px 8px 0 rgba($black, $bmd-shadow-ambient-opacity); 16 | 17 | $bmd-shadow-4dp: 0 4px 5px 0 rgba($black, $bmd-shadow-penumbra-opacity), 18 | 0 1px 10px 0 rgba($black, $bmd-shadow-ambient-opacity), 19 | 0 2px 4px -1px rgba($black, $bmd-shadow-umbra-opacity); 20 | 21 | $bmd-shadow-6dp: 0 6px 10px 0 rgba($black, $bmd-shadow-penumbra-opacity), 22 | 0 1px 18px 0 rgba($black, $bmd-shadow-ambient-opacity), 23 | 0 3px 5px -1px rgba($black, $bmd-shadow-umbra-opacity); 24 | 25 | $bmd-shadow-8dp: 0 8px 10px 1px rgba($black, $bmd-shadow-penumbra-opacity), 26 | 0 3px 14px 2px rgba($black, $bmd-shadow-ambient-opacity), 27 | 0 5px 5px -3px rgba($black, $bmd-shadow-umbra-opacity); 28 | 29 | $bmd-shadow-16dp: 0 16px 24px 2px rgba($black, $bmd-shadow-penumbra-opacity), 30 | 0 6px 30px 5px rgba($black, $bmd-shadow-ambient-opacity), 31 | 0 8px 10px -5px rgba($black, $bmd-shadow-umbra-opacity); 32 | 33 | $bmd-shadow-24dp: 0 9px 46px 8px rgba($black, $bmd-shadow-penumbra-opacity), 34 | 0 11px 15px -7px rgba($black, $bmd-shadow-ambient-opacity), 35 | 0 24px 38px 3px rgba($black, $bmd-shadow-umbra-opacity); 36 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/mixins/_grid.scss: -------------------------------------------------------------------------------- 1 | /// Grid system 2 | // 3 | // Generate semantic grid columns with these mixins. 4 | 5 | @mixin make-container() { 6 | width: 100%; 7 | padding-right: ($grid-gutter-width / 2); 8 | padding-left: ($grid-gutter-width / 2); 9 | margin-right: auto; 10 | margin-left: auto; 11 | } 12 | 13 | 14 | // For each breakpoint, define the maximum width of the container in a media query 15 | @mixin make-container-max-widths($max-widths: $container-max-widths, $breakpoints: $grid-breakpoints) { 16 | @each $breakpoint, $container-max-width in $max-widths { 17 | @include media-breakpoint-up($breakpoint, $breakpoints) { 18 | max-width: $container-max-width; 19 | } 20 | } 21 | } 22 | 23 | @mixin make-row() { 24 | display: flex; 25 | flex-wrap: wrap; 26 | margin-right: ($grid-gutter-width / -2); 27 | margin-left: ($grid-gutter-width / -2); 28 | } 29 | 30 | @mixin make-col-ready() { 31 | position: relative; 32 | // Prevent columns from becoming too narrow when at smaller grid tiers by 33 | // always setting `width: 100%;`. This works because we use `flex` values 34 | // later on to override this initial width. 35 | width: 100%; 36 | min-height: 1px; // Prevent collapsing 37 | padding-right: ($grid-gutter-width / 2); 38 | padding-left: ($grid-gutter-width / 2); 39 | } 40 | 41 | @mixin make-col($size, $columns: $grid-columns) { 42 | flex: 0 0 percentage($size / $columns); 43 | // Add a `max-width` to ensure content within each column does not blow out 44 | // the width of the column. Applies to IE10+ and Firefox. Chrome and Safari 45 | // do not appear to require this. 46 | max-width: percentage($size / $columns); 47 | } 48 | 49 | @mixin make-col-offset($size, $columns: $grid-columns) { 50 | $num: $size / $columns; 51 | margin-left: if($num == 0, 0, percentage($num)); 52 | } 53 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/_headers.scss: -------------------------------------------------------------------------------- 1 | .page-header{ 2 | min-height: 100vh; 3 | max-height: 1000px; 4 | display: flex !important; 5 | height: 100%; 6 | padding: 0; 7 | color: $white-color; 8 | position: relative; 9 | 10 | .page-header-image{ 11 | position: absolute; 12 | background-size: cover; 13 | background-position: center center; 14 | width: 100%; 15 | height: 100%; 16 | z-index: -1; 17 | } 18 | 19 | .content-center{ 20 | position: absolute; 21 | top: 50%; 22 | left: 50%; 23 | z-index: 2; 24 | -ms-transform: translate(-50%, -50%); 25 | -webkit-transform: translate(-50%, -50%); 26 | transform: translate(-50%, -50%); 27 | text-align: center; 28 | color: #FFFFFF; 29 | padding: 0 15px; 30 | width: 100%; 31 | max-width: 880px; 32 | } 33 | 34 | footer{ 35 | position: absolute; 36 | bottom: 0; 37 | width: 100%; 38 | } 39 | 40 | .container{ 41 | height: 100%; 42 | z-index: 1; 43 | } 44 | 45 | .category, 46 | .description{ 47 | color: $opacity-8; 48 | } 49 | 50 | &.page-header-small{ 51 | min-height: 60vh; 52 | max-height: 440px; 53 | } 54 | 55 | &.page-header-mini{ 56 | min-height: 40vh; 57 | max-height: 340px; 58 | } 59 | 60 | .title{ 61 | margin-bottom: 15px; 62 | } 63 | .title + h4{ 64 | margin-top: 10px; 65 | } 66 | 67 | &:after, 68 | &:before{ 69 | position: absolute; 70 | z-index: 0; 71 | width: 100%; 72 | height: 100%; 73 | display: block; 74 | left: 0; 75 | top: 0; 76 | content: ""; 77 | } 78 | 79 | &:before{ 80 | background-color: rgba(0,0,0,.3); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/_type.scss: -------------------------------------------------------------------------------- 1 | html * { 2 | -webkit-font-smoothing: antialiased; 3 | -moz-osx-font-smoothing: grayscale; 4 | } 5 | 6 | body, h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4 { 7 | font-family: $font-family-sans-serif; 8 | font-weight: 300; 9 | line-height: 1.5em; 10 | } 11 | 12 | 13 | h1, .h1 { 14 | font-size: $font-size-h1; 15 | line-height: 1.15em; 16 | } 17 | h2, .h2{ 18 | font-size: $font-size-h2; 19 | } 20 | h3, .h3{ 21 | font-size: $font-size-h3; 22 | line-height: 1.4em; 23 | margin: 20px 0 10px; 24 | } 25 | h4, .h4{ 26 | font-size: $font-size-h4; 27 | line-height: 1.4em; 28 | font-weight: 300; 29 | } 30 | h5, .h5 { 31 | font-size: $font-size-h5; 32 | line-height: 1.4em; 33 | margin-bottom: 15px; 34 | } 35 | h6, .h6{ 36 | font-size: $font-size-h6; 37 | text-transform: uppercase; 38 | font-weight: $font-weight-bold; 39 | } 40 | 41 | .title, 42 | .card-title, 43 | .info-title, 44 | .footer-brand, 45 | .footer-big h5, 46 | .footer-big h4, 47 | .media .media-heading{ 48 | //font-weight: $font-weight-extra-bold; 49 | // font-family: $font-family-serif; 50 | 51 | &, 52 | a{ 53 | color: $black-color; 54 | text-decoration: none; 55 | } 56 | } 57 | 58 | .card-blog .card-title{ 59 | font-weight: $font-weight-extra-bold; 60 | } 61 | 62 | h2.title{ 63 | margin-bottom: $margin-base * 2; 64 | } 65 | 66 | .description, 67 | .card-description, 68 | .footer-big p{ 69 | color: $gray-light; 70 | } 71 | 72 | .text-warning { 73 | color: $brand-warning !important; 74 | } 75 | .text-primary { 76 | color: $brand-primary !important; 77 | } 78 | .text-danger { 79 | color: $brand-danger !important; 80 | } 81 | .text-success { 82 | color: $brand-success !important; 83 | } 84 | .text-info { 85 | color: $brand-info !important; 86 | } 87 | .text-rose{ 88 | color: $brand-rose !important; 89 | } 90 | .text-gray{ 91 | color: $gray-color !important; 92 | } 93 | -------------------------------------------------------------------------------- /web/models/UserForgotForm.php: -------------------------------------------------------------------------------- 1 | 7 | * @link https://www.coderseden.com 8 | * @copyright 2020 Material Dashboard Yii2 (https://www.coderseden.com) 9 | * @license MIT - https://www.coderseden.com 10 | * @since 1.0 11 | */ 12 | 13 | namespace app\models; 14 | 15 | use yii\base\Model; 16 | 17 | /** 18 | * Class UserForgotForm 19 | * @package app\models 20 | */ 21 | class UserForgotForm extends Model 22 | { 23 | /** 24 | * @var string 25 | */ 26 | public $email = ''; 27 | 28 | /** 29 | * @return array the validation rules. 30 | */ 31 | public function rules() 32 | { 33 | return [ 34 | [['email'], 'required'], 35 | [['email'], 'email'], 36 | [['email'], 'validateEmail'], 37 | ]; 38 | } 39 | 40 | /** 41 | * Validates the email. 42 | * This method serves as the inline validation for email. 43 | * 44 | * @param string $attribute the attribute currently being validated 45 | * @param array $params the additional name-value pairs given in the rule 46 | */ 47 | public function validateEmail($attribute, $params) 48 | { 49 | if ($this->hasErrors()) { 50 | return; 51 | } 52 | 53 | $model = User::findOne([ 54 | 'email' => $this->$attribute, 55 | 'status' => 'active' 56 | ]); 57 | 58 | if (empty($model)) { 59 | $this->addError('email', 'Invalid email address!'); 60 | } 61 | } 62 | 63 | /** 64 | * @return bool 65 | * @throws \yii\base\Exception 66 | */ 67 | public function sendEmail() { 68 | if ( ! $this->validate() ) { 69 | return false; 70 | } 71 | 72 | if ( ! ( $model = User::findByEmail( $this->email ) ) ) { 73 | return false; 74 | } 75 | 76 | $model->password_reset_key = \Yii::$app->security->generateRandomString(); 77 | $model->save( false ); 78 | 79 | //here the email function 80 | 81 | return true; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | 3 | ========================================================= 4 | * Material Dashboard - v2.1.0 5 | ========================================================= 6 | 7 | * Product Page: https://www.creative-tim.com/product/material-dashboard 8 | * Copyright 2020 Creative Tim (http://www.creative-tim.com) 9 | 10 | ========================================================= 11 | 12 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 13 | 14 | */ 15 | 16 | @import "material-dashboard/variables"; 17 | @import "material-dashboard/mixins"; 18 | @import "material-dashboard/core-bootstrap"; 19 | 20 | // Core Components 21 | @import "material-dashboard/buttons"; 22 | @import "material-dashboard/checkboxes"; 23 | @import "material-dashboard/radios"; 24 | @import "material-dashboard/forms"; 25 | @import "material-dashboard/input-group"; 26 | @import "material-dashboard/images"; 27 | @import "material-dashboard/navbar"; 28 | @import "material-dashboard/alerts"; 29 | @import "material-dashboard/headers"; 30 | @import "material-dashboard/type"; 31 | @import "material-dashboard/tabs"; 32 | @import "material-dashboard/tooltip"; 33 | @import "material-dashboard/popover"; 34 | @import "material-dashboard/dropdown"; 35 | @import "material-dashboard/togglebutton"; 36 | @import "material-dashboard/ripples"; 37 | @import "material-dashboard/footers"; 38 | @import "material-dashboard/sidebar-and-main-panel"; 39 | @import "material-dashboard/fixed-plugin"; 40 | @import "material-dashboard/tables"; 41 | @import "material-dashboard/misc"; 42 | @import "material-dashboard/social-buttons"; 43 | 44 | @import "material-dashboard/cards"; 45 | @import "material-dashboard/cards/card-stats"; 46 | @import "material-dashboard/cards/card-profile"; 47 | @import "material-dashboard/cards/card-plain"; 48 | 49 | //plugin scss 50 | @import "material-dashboard/plugins/animate"; 51 | @import "material-dashboard/plugins/chartist"; 52 | @import "material-dashboard/plugins/perfect-scrollbar"; 53 | 54 | @import "material-dashboard/responsive"; 55 | -------------------------------------------------------------------------------- /web/views/site/forgot.php: -------------------------------------------------------------------------------- 1 | 7 | * @link https://www.coderseden.com 8 | * @copyright 2020 Material Dashboard Yii2 (https://www.coderseden.com) 9 | * @license MIT - https://www.coderseden.com 10 | * @since 1.0 11 | */ 12 | 13 | use yii\bootstrap4\ActiveForm; 14 | ?> 15 |
    16 |
    17 |
    18 | 'forgot-password-form', 20 | 'method' => 'post', 21 | ] ); ?> 22 | 49 | 50 |
    51 |
    52 |
    -------------------------------------------------------------------------------- /web/models/UserSearch.php: -------------------------------------------------------------------------------- 1 | 7 | * @link https://www.coderseden.com 8 | * @copyright 2020 Material Dashboard Yii2 (https://www.coderseden.com) 9 | * @license MIT - https://www.coderseden.com 10 | * @since 1.0 11 | */ 12 | 13 | namespace app\models; 14 | 15 | use yii\base\Model; 16 | use yii\data\ActiveDataProvider; 17 | 18 | /** 19 | * Class UserSearch 20 | * @package app\models 21 | */ 22 | class UserSearch extends User 23 | { 24 | /** 25 | * @return array 26 | */ 27 | public function rules() 28 | { 29 | return [ 30 | [['user_id'], 'integer'], 31 | [['group_id', 'first_name', 'last_name', 'email', 'password', 'status', 'created_at', 'updated_at'], 'safe'], 32 | ]; 33 | } 34 | 35 | /** 36 | * @return array 37 | */ 38 | public function scenarios() 39 | { 40 | // bypass scenarios() implementation in the parent class 41 | return Model::scenarios(); 42 | } 43 | 44 | /** 45 | * @param $params 46 | * 47 | * @return ActiveDataProvider 48 | */ 49 | public function search($params) 50 | { 51 | $query = User::find(); 52 | 53 | // add conditions that should always apply here 54 | 55 | $dataProvider = new ActiveDataProvider([ 56 | 'query' => $query, 57 | ]); 58 | 59 | $this->load($params); 60 | 61 | if (!$this->validate()) { 62 | // uncomment the following line if you do not want to return any records when validation fails 63 | // $query->where('0=1'); 64 | return $dataProvider; 65 | } 66 | 67 | // grid filtering conditions 68 | $query->andFilterWhere([ 69 | 'user_id' => $this->user_id, 70 | 'updated_at' => $this->updated_at, 71 | ]); 72 | 73 | $query->andFilterWhere(['like', 'first_name', $this->first_name]) 74 | ->andFilterWhere(['like', 'last_name', $this->last_name]) 75 | ->andFilterWhere(['like', 'email', $this->email]) 76 | ->andFilterWhere(['like', 'password', $this->password]) 77 | ->andFilterWhere(['like', 'created_at', $this->created_at]) 78 | ->andFilterWhere(['=', 'status', $this->status]); 79 | return $dataProvider; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/_pagination.scss: -------------------------------------------------------------------------------- 1 | .pagination { 2 | display: flex; 3 | @include list-unstyled(); 4 | @include border-radius(); 5 | } 6 | 7 | .page-link { 8 | position: relative; 9 | display: block; 10 | padding: $pagination-padding-y $pagination-padding-x; 11 | margin-left: -$pagination-border-width; 12 | line-height: $pagination-line-height; 13 | color: $pagination-color; 14 | background-color: $pagination-bg; 15 | border: $pagination-border-width solid $pagination-border-color; 16 | 17 | &:hover { 18 | color: $pagination-hover-color; 19 | text-decoration: none; 20 | background-color: $pagination-hover-bg; 21 | border-color: $pagination-hover-border-color; 22 | } 23 | 24 | &:focus { 25 | z-index: 2; 26 | outline: 0; 27 | box-shadow: $pagination-focus-box-shadow; 28 | } 29 | 30 | // Opinionated: add "hand" cursor to non-disabled .page-link elements 31 | &:not(:disabled):not(.disabled) { 32 | cursor: pointer; 33 | } 34 | } 35 | 36 | .page-item { 37 | &:first-child { 38 | .page-link { 39 | margin-left: 0; 40 | @include border-left-radius($border-radius); 41 | } 42 | } 43 | &:last-child { 44 | .page-link { 45 | @include border-right-radius($border-radius); 46 | } 47 | } 48 | 49 | &.active .page-link { 50 | z-index: 1; 51 | color: $pagination-active-color; 52 | background-color: $pagination-active-bg; 53 | border-color: $pagination-active-border-color; 54 | } 55 | 56 | &.disabled .page-link { 57 | color: $pagination-disabled-color; 58 | pointer-events: none; 59 | // Opinionated: remove the "hand" cursor set previously for .page-link 60 | cursor: auto; 61 | background-color: $pagination-disabled-bg; 62 | border-color: $pagination-disabled-border-color; 63 | } 64 | } 65 | 66 | 67 | // 68 | // Sizing 69 | // 70 | 71 | .pagination-lg { 72 | @include pagination-size($pagination-padding-y-lg, $pagination-padding-x-lg, $font-size-lg, $line-height-lg, $border-radius-lg); 73 | } 74 | 75 | .pagination-sm { 76 | @include pagination-size($pagination-padding-y-sm, $pagination-padding-x-sm, $font-size-sm, $line-height-sm, $border-radius-sm); 77 | } 78 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/_core-bootstrap.scss: -------------------------------------------------------------------------------- 1 | // FIXME: only necessary because there isn't an underscored file - see https://github.com/twbs/bootstrap/issues/18350 2 | //@import "../bower_components/bootstrap/scss/ 3 | //@import "../../bootstrap/scss/ 4 | 5 | // Core variables and mixins 6 | @import "./bootstrap/scss/functions"; 7 | @import "./bootstrap/scss/variables"; 8 | @import "./bootstrap/scss/mixins"; 9 | 10 | // #853 start - https://github.com/twbs/bootstrap/pull/18976/files 11 | // hack 12 | @mixin pull-left { 13 | float: left !important; 14 | @if $enable-flex { 15 | margin-right: auto; 16 | } 17 | } 18 | @mixin pull-right { 19 | float: right !important; 20 | @if $enable-flex { 21 | margin-left: auto; 22 | } 23 | } 24 | // #853 end - https://github.com/twbs/bootstrap/pull/18976/files 25 | 26 | // Reset and dependencies 27 | @import "./bootstrap/scss/reboot"; 28 | @import "./bootstrap/scss/print"; 29 | 30 | // Core CSS 31 | @import "./bootstrap/scss/reboot"; 32 | @import "./bootstrap/scss/type"; 33 | @import "./bootstrap/scss/images"; 34 | @import "./bootstrap/scss/code"; 35 | @import "./bootstrap/scss/grid"; 36 | @import "./bootstrap/scss/tables"; 37 | @import "./bootstrap/scss/forms"; 38 | @import "./bootstrap/scss/buttons"; 39 | @import "./bootstrap/scss/transitions"; 40 | 41 | // Components 42 | @import "./bootstrap/scss/dropdown"; 43 | @import "./bootstrap/scss/button-group"; 44 | @import "./bootstrap/scss/input-group"; 45 | @import "./bootstrap/scss/custom-forms"; 46 | @import "./bootstrap/scss/nav"; 47 | @import "./bootstrap/scss/navbar"; 48 | @import "./bootstrap/scss/card"; 49 | @import "./bootstrap/scss/breadcrumb"; 50 | @import "./bootstrap/scss/pagination"; 51 | @import "./bootstrap/scss/jumbotron"; 52 | @import "./bootstrap/scss/alert"; 53 | @import "./bootstrap/scss/progress"; 54 | @import "./bootstrap/scss/media"; 55 | @import "./bootstrap/scss/list-group"; 56 | @import "./bootstrap/scss/close"; 57 | @import "./bootstrap/scss/badge"; 58 | 59 | // Components w/ JavaScript 60 | @import "./bootstrap/scss/modal"; 61 | @import "./bootstrap/scss/tooltip"; 62 | @import "./bootstrap/scss/popover"; 63 | @import "./bootstrap/scss/carousel"; 64 | 65 | // Utility classes 66 | @import "./bootstrap/scss/utilities"; 67 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/mixins/_grid-framework.scss: -------------------------------------------------------------------------------- 1 | // Framework grid generation 2 | // 3 | // Used only by Bootstrap to generate the correct number of grid classes given 4 | // any value of `$grid-columns`. 5 | 6 | @mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) { 7 | // Common properties for all breakpoints 8 | %grid-column { 9 | position: relative; 10 | width: 100%; 11 | min-height: 1px; // Prevent columns from collapsing when empty 12 | padding-right: ($gutter / 2); 13 | padding-left: ($gutter / 2); 14 | } 15 | 16 | @each $breakpoint in map-keys($breakpoints) { 17 | $infix: breakpoint-infix($breakpoint, $breakpoints); 18 | 19 | // Allow columns to stretch full width below their breakpoints 20 | @for $i from 1 through $columns { 21 | .col#{$infix}-#{$i} { 22 | @extend %grid-column; 23 | } 24 | } 25 | .col#{$infix}, 26 | .col#{$infix}-auto { 27 | @extend %grid-column; 28 | } 29 | 30 | @include media-breakpoint-up($breakpoint, $breakpoints) { 31 | // Provide basic `.col-{bp}` classes for equal-width flexbox columns 32 | .col#{$infix} { 33 | flex-basis: 0; 34 | flex-grow: 1; 35 | max-width: 100%; 36 | } 37 | .col#{$infix}-auto { 38 | flex: 0 0 auto; 39 | width: auto; 40 | max-width: none; // Reset earlier grid tiers 41 | } 42 | 43 | @for $i from 1 through $columns { 44 | .col#{$infix}-#{$i} { 45 | @include make-col($i, $columns); 46 | } 47 | } 48 | 49 | .order#{$infix}-first { order: -1; } 50 | 51 | .order#{$infix}-last { order: $columns + 1; } 52 | 53 | @for $i from 0 through $columns { 54 | .order#{$infix}-#{$i} { order: $i; } 55 | } 56 | 57 | // `$columns - 1` because offsetting by the width of an entire row isn't possible 58 | @for $i from 0 through ($columns - 1) { 59 | @if not ($infix == "" and $i == 0) { // Avoid emitting useless .offset-0 60 | .offset#{$infix}-#{$i} { 61 | @include make-col-offset($i, $columns); 62 | } 63 | } 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/mixins/_gradients.scss: -------------------------------------------------------------------------------- 1 | // Gradients 2 | 3 | @mixin gradient-bg($color) { 4 | @if $enable-gradients { 5 | background: $color linear-gradient(180deg, mix($body-bg, $color, 15%), $color) repeat-x; 6 | } @else { 7 | background-color: $color; 8 | } 9 | } 10 | 11 | // Horizontal gradient, from left to right 12 | // 13 | // Creates two color stops, start and end, by specifying a color and position for each color stop. 14 | @mixin gradient-x($start-color: #555, $end-color: #333, $start-percent: 0%, $end-percent: 100%) { 15 | background-image: linear-gradient(to right, $start-color $start-percent, $end-color $end-percent); 16 | background-repeat: repeat-x; 17 | } 18 | 19 | // Vertical gradient, from top to bottom 20 | // 21 | // Creates two color stops, start and end, by specifying a color and position for each color stop. 22 | @mixin gradient-y($start-color: #555, $end-color: #333, $start-percent: 0%, $end-percent: 100%) { 23 | background-image: linear-gradient(to bottom, $start-color $start-percent, $end-color $end-percent); 24 | background-repeat: repeat-x; 25 | } 26 | 27 | @mixin gradient-directional($start-color: #555, $end-color: #333, $deg: 45deg) { 28 | background-image: linear-gradient($deg, $start-color, $end-color); 29 | background-repeat: repeat-x; 30 | } 31 | @mixin gradient-x-three-colors($start-color: #00b3ee, $mid-color: #7a43b6, $color-stop: 50%, $end-color: #c3325f) { 32 | background-image: linear-gradient(to right, $start-color, $mid-color $color-stop, $end-color); 33 | background-repeat: no-repeat; 34 | } 35 | @mixin gradient-y-three-colors($start-color: #00b3ee, $mid-color: #7a43b6, $color-stop: 50%, $end-color: #c3325f) { 36 | background-image: linear-gradient($start-color, $mid-color $color-stop, $end-color); 37 | background-repeat: no-repeat; 38 | } 39 | @mixin gradient-radial($inner-color: #555, $outer-color: #333) { 40 | background-image: radial-gradient(circle, $inner-color, $outer-color); 41 | background-repeat: no-repeat; 42 | } 43 | @mixin gradient-striped($color: rgba(255,255,255,.15), $angle: 45deg) { 44 | background-image: linear-gradient($angle, $color 25%, transparent 25%, transparent 50%, $color 50%, $color 75%, transparent 75%, transparent); 45 | } 46 | -------------------------------------------------------------------------------- /web/tests/functional/ContactFormCest.php: -------------------------------------------------------------------------------- 1 | amOnPage(['site/contact']); 8 | } 9 | 10 | public function openContactPage(\FunctionalTester $I) 11 | { 12 | $I->see('Contact', 'h1'); 13 | } 14 | 15 | public function submitEmptyForm(\FunctionalTester $I) 16 | { 17 | $I->submitForm('#contact-form', []); 18 | $I->expectTo('see validations errors'); 19 | $I->see('Contact', 'h1'); 20 | $I->see('Name cannot be blank'); 21 | $I->see('Email cannot be blank'); 22 | $I->see('Subject cannot be blank'); 23 | $I->see('Body cannot be blank'); 24 | $I->see('The verification code is incorrect'); 25 | } 26 | 27 | public function submitFormWithIncorrectEmail(\FunctionalTester $I) 28 | { 29 | $I->submitForm('#contact-form', [ 30 | 'ContactForm[name]' => 'tester', 31 | 'ContactForm[email]' => 'tester.email', 32 | 'ContactForm[subject]' => 'test subject', 33 | 'ContactForm[body]' => 'test content', 34 | 'ContactForm[verifyCode]' => 'testme', 35 | ]); 36 | $I->expectTo('see that email address is wrong'); 37 | $I->dontSee('Name cannot be blank', '.help-inline'); 38 | $I->see('Email is not a valid email address.'); 39 | $I->dontSee('Subject cannot be blank', '.help-inline'); 40 | $I->dontSee('Body cannot be blank', '.help-inline'); 41 | $I->dontSee('The verification code is incorrect', '.help-inline'); 42 | } 43 | 44 | public function submitFormSuccessfully(\FunctionalTester $I) 45 | { 46 | $I->submitForm('#contact-form', [ 47 | 'ContactForm[name]' => 'tester', 48 | 'ContactForm[email]' => 'tester@example.com', 49 | 'ContactForm[subject]' => 'test subject', 50 | 'ContactForm[body]' => 'test content', 51 | 'ContactForm[verifyCode]' => 'testme', 52 | ]); 53 | $I->seeEmailIsSent(); 54 | $I->dontSeeElement('#contact-form'); 55 | $I->see('Thank you for contacting us. We will respond to you as soon as possible.'); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/_popups.scss: -------------------------------------------------------------------------------- 1 | .popover{ 2 | font-size: $font-size-base; 3 | box-shadow: 0px 10px 50px 0px rgba(0, 0, 0, 0.2); 4 | border: none; 5 | line-height: 1.7; 6 | max-width: 240px; 7 | 8 | &.bs-popover-top .arrow:before, 9 | &.bs-popover-left .arrow:before, 10 | &.bs-popover-right .arrow:before, 11 | &.bs-popover-bottom .arrow:before,{ 12 | border-top-color: transparent; 13 | border-left-color: transparent; 14 | border-right-color: transparent; 15 | border-bottom-color: transparent; 16 | } 17 | 18 | .popover-header{ 19 | color: $default-color-opacity; 20 | font-size: $font-size-base; 21 | text-transform: capitalize; 22 | font-weight: $font-weight-semi; 23 | margin: 0; 24 | margin-top: 5px; 25 | border: none; 26 | background-color: transparent; 27 | } 28 | 29 | &:before{ 30 | display: none; 31 | } 32 | 33 | &.bs-tether-element-attached-top:after{ 34 | border-bottom-color:$white-color; 35 | top: -9px; 36 | } 37 | 38 | &.popover-primary{ 39 | @include popover-color($primary-color, $white-color); 40 | } 41 | 42 | &.popover-info{ 43 | @include popover-color($info-color, $white-color); 44 | } 45 | 46 | &.popover-warning{ 47 | @include popover-color($warning-color, $white-color); 48 | } 49 | 50 | &.popover-danger{ 51 | @include popover-color($danger-color, $white-color); 52 | } 53 | 54 | &.popover-success{ 55 | @include popover-color($success-color, $white-color); 56 | } 57 | } 58 | 59 | 60 | .tooltip{ 61 | &.bs-tooltip-right .arrow:before{ 62 | border-right-color:$white-color; 63 | } 64 | 65 | &.bs-tooltip-top .arrow:before{ 66 | border-top-color:$white-color; 67 | } 68 | 69 | &.bs-tooltip-bottom .arrow:before{ 70 | border-bottom-color:$white-color; 71 | } 72 | 73 | &.bs-tooltip-left .arrow:before{ 74 | border-left-color:$white-color; 75 | } 76 | } 77 | 78 | .tooltip-inner{ 79 | padding: $padding-base-vertical $padding-base-horizontal; 80 | min-width: 130px; 81 | background-color: $white-color; 82 | font-size: $font-size-base; 83 | color: inherit; 84 | box-shadow: 0px 5px 25px 0px rgba(0, 0, 0, 0.2); 85 | } 86 | -------------------------------------------------------------------------------- /web/config/web.php: -------------------------------------------------------------------------------- 1 | 'basic', 8 | 'basePath' => dirname(__DIR__), 9 | 'bootstrap' => ['log'], 10 | 'aliases' => [ 11 | '@bower' => '@vendor/bower-asset', 12 | '@npm' => '@vendor/npm-asset', 13 | ], 14 | 'components' => [ 15 | 'assetManager' => [ 16 | 'bundles' => [ 17 | 'yii\web\JqueryAsset' => [ 18 | 'js'=>[] 19 | ], 20 | ], 21 | ], 22 | 'request' => [ 23 | // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation 24 | 'cookieValidationKey' => 'LxItaVNs937UxDgbhAE0Rwy_x06D8R4i', 25 | ], 26 | 'cache' => [ 27 | 'class' => 'yii\caching\FileCache', 28 | ], 29 | 'user' => [ 30 | 'identityClass' => 'app\models\User', 31 | 'enableAutoLogin' => true, 32 | ], 33 | 'errorHandler' => [ 34 | 'errorAction' => 'site/error', 35 | ], 36 | 'mailer' => [ 37 | 'class' => 'yii\swiftmailer\Mailer', 38 | // send all mails to a file by default. You have to set 39 | // 'useFileTransport' to false and configure a transport 40 | // for the mailer to send real emails. 41 | 'useFileTransport' => true, 42 | ], 43 | 'log' => [ 44 | 'traceLevel' => YII_DEBUG ? 3 : 0, 45 | 'targets' => [ 46 | [ 47 | 'class' => 'yii\log\FileTarget', 48 | 'levels' => ['error', 'warning'], 49 | ], 50 | ], 51 | ], 52 | 'db' => $db, 53 | 'urlManager' => [ 54 | 'enablePrettyUrl' => true, 55 | 'showScriptName' => false, 56 | 'rules' => [ 57 | ], 58 | ], 59 | ], 60 | 'params' => $params, 61 | ]; 62 | 63 | if (YII_ENV_DEV) { 64 | // configuration adjustments for 'dev' environment 65 | $config['bootstrap'][] = 'debug'; 66 | $config['modules']['debug'] = [ 67 | 'class' => 'yii\debug\Module', 68 | 'allowedIPs' => ['*'], 69 | ]; 70 | 71 | $config['bootstrap'][] = 'gii'; 72 | $config['modules']['gii'] = [ 73 | 'class' => 'yii\gii\Module', 74 | 'allowedIPs' => ['*'] 75 | ]; 76 | } 77 | 78 | return $config; 79 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/_togglebutton.scss: -------------------------------------------------------------------------------- 1 | .togglebutton { 2 | vertical-align: middle; 3 | &, label, input, .toggle { 4 | user-select: none; 5 | } 6 | label { 7 | cursor: pointer; 8 | color: $mdb-toggle-label-color; 9 | @include mdb-label-color-toggle-focus(); 10 | 11 | // Hide original checkbox 12 | input[type=checkbox] { 13 | opacity: 0; 14 | width: 0; 15 | height: 0; 16 | } 17 | 18 | .toggle { 19 | text-align: left; // Issue #737 horizontal form 20 | margin-left: 5px; 21 | } 22 | // Switch bg off and disabled 23 | .toggle, 24 | input[type=checkbox][disabled] + .toggle { 25 | content: ""; 26 | display: inline-block; 27 | width: 30px; 28 | height: 15px; 29 | background-color: rgba(80, 80, 80, 0.7); 30 | border-radius: 15px; 31 | margin-right: 15px; 32 | transition: background 0.3s ease; 33 | vertical-align: middle; 34 | } 35 | // Handle off 36 | .toggle:after { 37 | content: ""; 38 | display: inline-block; 39 | width: 20px; 40 | height: 20px; 41 | background-color: #FFFFFF; 42 | border-radius: 20px; 43 | position: relative; 44 | box-shadow: 0 1px 3px 1px rgba(0, 0, 0, 0.4); 45 | left: -5px; 46 | top: -2.5px; 47 | border: 1px solid $mdb-checkbox-border-color; 48 | transition: left 0.3s ease, background 0.3s ease, box-shadow 0.1s ease; 49 | } 50 | input[type=checkbox] { 51 | // Handle disabled 52 | &[disabled] { 53 | & + .toggle:after, 54 | &:checked + .toggle:after { 55 | background-color: #BDBDBD; 56 | } 57 | } 58 | 59 | & + .toggle:active:after, 60 | &[disabled] + .toggle:active:after { 61 | box-shadow: 0 1px 3px 1px rgba(0, 0, 0, 0.4), 0 0 0 15px rgba(0, 0, 0, 0.1); 62 | } 63 | 64 | // Ripple off and disabled 65 | &:checked + .toggle:after { 66 | left: 15px; 67 | } 68 | } 69 | 70 | // set bg when checked 71 | input[type=checkbox]:checked { 72 | + .toggle { 73 | background-color: rgba($brand-primary, (70/100)); // Switch bg on 74 | } 75 | 76 | + .toggle:after { 77 | border-color: $brand-primary; // Handle on 78 | } 79 | 80 | + .toggle:active:after { 81 | box-shadow: 0 1px 3px 1px rgba(0, 0, 0, 0.4), 0 0 0 15px rgba($brand-primary, (10/100)); // Ripple on 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /web/vagrant/provision/once-as-root.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | #== Import script args == 4 | 5 | timezone=$(echo "$1") 6 | 7 | #== Bash helpers == 8 | 9 | function info { 10 | echo " " 11 | echo "--> $1" 12 | echo " " 13 | } 14 | 15 | #== Provision script == 16 | 17 | info "Provision-script user: `whoami`" 18 | 19 | export DEBIAN_FRONTEND=noninteractive 20 | 21 | info "Configure timezone" 22 | timedatectl set-timezone ${timezone} --no-ask-password 23 | 24 | info "Prepare root password for MySQL" 25 | debconf-set-selections <<< "mariadb-server-10.0 mysql-server/root_password password \"''\"" 26 | debconf-set-selections <<< "mariadb-server-10.0 mysql-server/root_password_again password \"''\"" 27 | echo "Done!" 28 | 29 | info "Update OS software" 30 | apt-get update 31 | apt-get upgrade -y 32 | 33 | info "Install additional software" 34 | apt-get install -y php7.0-curl php7.0-cli php7.0-intl php7.0-mysqlnd php7.0-gd php7.0-fpm php7.0-mbstring php7.0-xml unzip nginx mariadb-server-10.0 php.xdebug 35 | 36 | info "Configure MySQL" 37 | sed -i "s/.*bind-address.*/bind-address = 0.0.0.0/" /etc/mysql/mariadb.conf.d/50-server.cnf 38 | mysql -uroot <<< "CREATE USER 'root'@'%' IDENTIFIED BY ''" 39 | mysql -uroot <<< "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'" 40 | mysql -uroot <<< "DROP USER 'root'@'localhost'" 41 | mysql -uroot <<< "FLUSH PRIVILEGES" 42 | echo "Done!" 43 | 44 | info "Configure PHP-FPM" 45 | sed -i 's/user = www-data/user = vagrant/g' /etc/php/7.0/fpm/pool.d/www.conf 46 | sed -i 's/group = www-data/group = vagrant/g' /etc/php/7.0/fpm/pool.d/www.conf 47 | sed -i 's/owner = www-data/owner = vagrant/g' /etc/php/7.0/fpm/pool.d/www.conf 48 | cat << EOF > /etc/php/7.0/mods-available/xdebug.ini 49 | zend_extension=xdebug.so 50 | xdebug.remote_enable=1 51 | xdebug.remote_connect_back=1 52 | xdebug.remote_port=9000 53 | xdebug.remote_autostart=1 54 | EOF 55 | echo "Done!" 56 | 57 | info "Configure NGINX" 58 | sed -i 's/user www-data/user vagrant/g' /etc/nginx/nginx.conf 59 | echo "Done!" 60 | 61 | info "Enabling site configuration" 62 | ln -s /app/vagrant/nginx/app.conf /etc/nginx/sites-enabled/app.conf 63 | echo "Done!" 64 | 65 | info "Removing default site configuration" 66 | rm /etc/nginx/sites-enabled/default 67 | echo "Done!" 68 | 69 | info "Initailize databases for MySQL" 70 | mysql -uroot <<< "CREATE DATABASE yii2basic" 71 | mysql -uroot <<< "CREATE DATABASE yii2basic_test" 72 | echo "Done!" 73 | 74 | info "Install composer" 75 | curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer -------------------------------------------------------------------------------- /web/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yiisoft/yii2-app-basic", 3 | "description": "Yii 2 Basic Project Template", 4 | "keywords": ["yii2", "framework", "basic", "project template"], 5 | "homepage": "http://www.yiiframework.com/", 6 | "type": "project", 7 | "license": "BSD-3-Clause", 8 | "support": { 9 | "issues": "https://github.com/yiisoft/yii2/issues?state=open", 10 | "forum": "http://www.yiiframework.com/forum/", 11 | "wiki": "http://www.yiiframework.com/wiki/", 12 | "irc": "irc://irc.freenode.net/yii", 13 | "source": "https://github.com/yiisoft/yii2" 14 | }, 15 | "minimum-stability": "stable", 16 | "require": { 17 | "php": ">=5.6.0", 18 | "yiisoft/yii2": "~2.0.14", 19 | "yiisoft/yii2-bootstrap": "~2.0.0", 20 | "yiisoft/yii2-swiftmailer": "~2.0.0 || ~2.1.0", 21 | "yiisoft/yii2-bootstrap4": "^2.0" 22 | }, 23 | "require-dev": { 24 | "yiisoft/yii2-debug": "~2.1.0", 25 | "yiisoft/yii2-gii": "~2.1.0", 26 | "yiisoft/yii2-faker": "~2.0.0", 27 | "codeception/codeception": "^4.0", 28 | "codeception/verify": "~0.5.0 || ~1.1.0", 29 | "codeception/specify": "~0.4.6", 30 | "symfony/browser-kit": ">=2.7 <=4.2.4", 31 | "codeception/module-filesystem": "^1.0.0", 32 | "codeception/module-yii2": "^1.0.0", 33 | "codeception/module-asserts": "^1.0.0" 34 | }, 35 | "config": { 36 | "process-timeout": 1800, 37 | "fxp-asset": { 38 | "enabled": false 39 | } 40 | }, 41 | "scripts": { 42 | "post-install-cmd": [ 43 | "yii\\composer\\Installer::postInstall" 44 | ], 45 | "post-create-project-cmd": [ 46 | "yii\\composer\\Installer::postCreateProject", 47 | "yii\\composer\\Installer::postInstall" 48 | ] 49 | }, 50 | "extra": { 51 | "yii\\composer\\Installer::postCreateProject": { 52 | "setPermission": [ 53 | { 54 | "runtime": "0777", 55 | "web/assets": "0777", 56 | "yii": "0755" 57 | } 58 | ] 59 | }, 60 | "yii\\composer\\Installer::postInstall": { 61 | "generateCookieValidationKey": [ 62 | "config/web.php" 63 | ] 64 | } 65 | }, 66 | "repositories": [ 67 | { 68 | "type": "composer", 69 | "url": "https://asset-packagist.org" 70 | } 71 | ] 72 | } 73 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/_tabs.scss: -------------------------------------------------------------------------------- 1 | 2 | .nav-tabs { 3 | border: 0; 4 | border-radius: $border-radius-base; 5 | padding: 0 15px; 6 | 7 | .nav-item { 8 | .nav-link { 9 | position: relative; 10 | color: $white-color; 11 | border: 0; 12 | margin: 0; 13 | border-radius: $border-radius-base; 14 | line-height: $mdb-btn-font-size-base * 2; 15 | text-transform: uppercase; 16 | font-size: $mdb-btn-font-size-base; 17 | padding: 10px 15px; 18 | background-color: transparent; 19 | transition: 0.3s background-color 0s; 20 | 21 | &:hover { 22 | border: 0; 23 | } 24 | } 25 | .nav-link, 26 | .nav-link:hover, 27 | .nav-link:focus { 28 | border: 0 !important; 29 | color: $white-color !important; 30 | font-weight: $font-weight-bold; 31 | } 32 | &.disabled .nav-link, 33 | &.disabled .nav-link:hover { 34 | color: rgba(255,255,255,0.5); 35 | } 36 | 37 | .material-icons{ 38 | margin: -1px 5px 0 0; 39 | } 40 | 41 | .nav-link.active{ 42 | background-color: rgba(255,255,255, .2); 43 | transition: 0.3s background-color 0.2s; 44 | } 45 | } 46 | } 47 | 48 | 49 | .nav-tabs { 50 | .nav-link { 51 | border-bottom: $bmd-nav-tabs-border-size solid transparent; 52 | } 53 | 54 | // colors 55 | @include bmd-tabs-color($bmd-nav-tabs-color, $bmd-nav-tabs-active-color, $bmd-nav-tabs-active-border-color, $bmd-nav-tabs-disabled-link-color, $bmd-nav-tabs-disabled-link-color-hover); 56 | 57 | &.header-primary { 58 | @include bmd-tabs-color($bmd-nav-tabs-primary-color, $bmd-nav-tabs-primary-active-color, $bmd-nav-tabs-primary-active-border-color, $bmd-nav-tabs-primary-disabled-link-color, $bmd-nav-tabs-primary-disabled-link-color-hover); 59 | } 60 | 61 | &.bg-inverse { 62 | @include bmd-tabs-color($bmd-nav-tabs-inverse-color, $bmd-nav-tabs-inverse-active-color, $bmd-nav-tabs-inverse-active-border-color, $bmd-nav-tabs-inverse-disabled-link-color, $bmd-nav-tabs-inverse-disabled-link-color-hover); 63 | } 64 | } 65 | 66 | 67 | 68 | .card-nav-tabs{ 69 | margin-top: 45px; 70 | 71 | .card-header{ 72 | margin-top: -30px !important; 73 | } 74 | } 75 | 76 | .tab-content .tab-pane .td-actions{ 77 | display: -webkit-box; 78 | display: -ms-flexbox; 79 | display: flex; 80 | } 81 | 82 | .card .tab-content .form-check{ 83 | margin-top: 6px; 84 | } 85 | -------------------------------------------------------------------------------- /web/widgets/Alert.php: -------------------------------------------------------------------------------- 1 | session->setFlash('error', 'This is the message'); 12 | * Yii::$app->session->setFlash('success', 'This is the message'); 13 | * Yii::$app->session->setFlash('info', 'This is the message'); 14 | * ``` 15 | * 16 | * Multiple messages could be set as follows: 17 | * 18 | * ```php 19 | * Yii::$app->session->setFlash('error', ['Error 1', 'Error 2']); 20 | * ``` 21 | * 22 | * @author Kartik Visweswaran 23 | * @author Alexander Makarov 24 | */ 25 | class Alert extends \yii\bootstrap\Widget 26 | { 27 | /** 28 | * @var array the alert types configuration for the flash messages. 29 | * This array is setup as $key => $value, where: 30 | * - key: the name of the session flash variable 31 | * - value: the bootstrap alert type (i.e. danger, success, info, warning) 32 | */ 33 | public $alertTypes = [ 34 | 'error' => 'alert-danger', 35 | 'danger' => 'alert-danger', 36 | 'success' => 'alert-success', 37 | 'info' => 'alert-info', 38 | 'warning' => 'alert-warning' 39 | ]; 40 | /** 41 | * @var array the options for rendering the close button tag. 42 | * Array will be passed to [[\yii\bootstrap\Alert::closeButton]]. 43 | */ 44 | public $closeButton = []; 45 | 46 | 47 | /** 48 | * {@inheritdoc} 49 | */ 50 | public function run() 51 | { 52 | $session = Yii::$app->session; 53 | $flashes = $session->getAllFlashes(); 54 | $appendClass = isset($this->options['class']) ? ' ' . $this->options['class'] : ''; 55 | 56 | foreach ($flashes as $type => $flash) { 57 | if (!isset($this->alertTypes[$type])) { 58 | continue; 59 | } 60 | 61 | foreach ((array) $flash as $i => $message) { 62 | echo \yii\bootstrap\Alert::widget([ 63 | 'body' => $message, 64 | 'closeButton' => $this->closeButton, 65 | 'options' => array_merge($this->options, [ 66 | 'id' => $this->getId() . '-' . $type . '-' . $i, 67 | 'class' => $this->alertTypes[$type] . $appendClass, 68 | ]), 69 | ]); 70 | } 71 | 72 | $session->removeFlash($type); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /web/migrations/m200216_223841_create_user_table.php: -------------------------------------------------------------------------------- 1 | 6 | * @link https://www.coderseden.com 7 | * @copyright 2020 Material Dashboard Yii2 (https://www.coderseden.com) 8 | * @license MIT - https://www.coderseden.com 9 | * @since 1.0 10 | */ 11 | 12 | use yii\db\Migration; 13 | 14 | /** 15 | * Handles the creation of table `{{%user}}`. 16 | */ 17 | class m200216_223841_create_user_table extends Migration 18 | { 19 | /** 20 | * @inheritdoc 21 | */ 22 | public function up() 23 | { 24 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB'; 25 | $this->createTable('{{%user}}', [ 26 | 'user_id' => $this->primaryKey(), 27 | 'group_id' => $this->integer()->defaultValue(null), 28 | 'first_name' => $this->string(100), 29 | 'last_name' => $this->string(100), 30 | 'email' => $this->string(150), 31 | 'auth_key' => $this->string(64), 32 | 'access_token' => $this->string(64), 33 | 'password' => $this->string(64), 34 | 'password_reset_key' => $this->string(32)->defaultValue(null), 35 | 'status' => $this->char(15)->notNull()->defaultValue('inactive'), 36 | 'created_at' => $this->dateTime()->notNull(), 37 | 'updated_at' => $this->dateTime()->notNull(), 38 | ], $tableOptions); 39 | 40 | $user = new \app\models\User(); 41 | $user->first_name = 'CodersEden'; 42 | $user->last_name = 'Team'; 43 | $user->email = 'hello@coderseden.com'; 44 | $user->passwd = 'admin123'; 45 | $user->status = 'active'; 46 | $user->save(); 47 | 48 | $user = new \app\models\User(); 49 | $user->first_name = 'John'; 50 | $user->last_name = 'Doe'; 51 | $user->email = 'john@mail.com'; 52 | $user->passwd = 'admin123'; 53 | $user->status = 'active'; 54 | $user->save(); 55 | 56 | $user = new \app\models\User(); 57 | $user->first_name = 'Mike'; 58 | $user->last_name = 'Harrison'; 59 | $user->email = 'mike@mail.com'; 60 | $user->passwd = 'admin123'; 61 | $user->status = 'active'; 62 | $user->save(); 63 | } 64 | 65 | /** 66 | * @inheritdoc 67 | */ 68 | public function down() 69 | { 70 | $this->getDb()->createCommand('SET FOREIGN_KEY_CHECKS = 0')->execute(); 71 | 72 | $this->dropTable('{{%user}}'); 73 | 74 | $this->getDb()->createCommand('SET FOREIGN_KEY_CHECKS = 1')->execute(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/utilities/_flex.scss: -------------------------------------------------------------------------------- 1 | // stylelint-disable declaration-no-important 2 | 3 | // Flex variation 4 | // 5 | // Custom styles for additional flex alignment options. 6 | 7 | @each $breakpoint in map-keys($grid-breakpoints) { 8 | @include media-breakpoint-up($breakpoint) { 9 | $infix: breakpoint-infix($breakpoint, $grid-breakpoints); 10 | 11 | .flex#{$infix}-row { flex-direction: row !important; } 12 | .flex#{$infix}-column { flex-direction: column !important; } 13 | .flex#{$infix}-row-reverse { flex-direction: row-reverse !important; } 14 | .flex#{$infix}-column-reverse { flex-direction: column-reverse !important; } 15 | 16 | .flex#{$infix}-wrap { flex-wrap: wrap !important; } 17 | .flex#{$infix}-nowrap { flex-wrap: nowrap !important; } 18 | .flex#{$infix}-wrap-reverse { flex-wrap: wrap-reverse !important; } 19 | 20 | .justify-content#{$infix}-start { justify-content: flex-start !important; } 21 | .justify-content#{$infix}-end { justify-content: flex-end !important; } 22 | .justify-content#{$infix}-center { justify-content: center !important; } 23 | .justify-content#{$infix}-between { justify-content: space-between !important; } 24 | .justify-content#{$infix}-around { justify-content: space-around !important; } 25 | 26 | .align-items#{$infix}-start { align-items: flex-start !important; } 27 | .align-items#{$infix}-end { align-items: flex-end !important; } 28 | .align-items#{$infix}-center { align-items: center !important; } 29 | .align-items#{$infix}-baseline { align-items: baseline !important; } 30 | .align-items#{$infix}-stretch { align-items: stretch !important; } 31 | 32 | .align-content#{$infix}-start { align-content: flex-start !important; } 33 | .align-content#{$infix}-end { align-content: flex-end !important; } 34 | .align-content#{$infix}-center { align-content: center !important; } 35 | .align-content#{$infix}-between { align-content: space-between !important; } 36 | .align-content#{$infix}-around { align-content: space-around !important; } 37 | .align-content#{$infix}-stretch { align-content: stretch !important; } 38 | 39 | .align-self#{$infix}-auto { align-self: auto !important; } 40 | .align-self#{$infix}-start { align-self: flex-start !important; } 41 | .align-self#{$infix}-end { align-self: flex-end !important; } 42 | .align-self#{$infix}-center { align-self: center !important; } 43 | .align-self#{$infix}-baseline { align-self: baseline !important; } 44 | .align-self#{$infix}-stretch { align-self: stretch !important; } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /web/models/UserLoginForm.php: -------------------------------------------------------------------------------- 1 | 7 | * @link https://www.coderseden.com 8 | * @copyright 2020 Material Dashboard Yii2 (https://www.coderseden.com) 9 | * @license MIT - https://www.coderseden.com 10 | * @since 1.0 11 | */ 12 | 13 | namespace app\models; 14 | 15 | use yii\base\Model; 16 | 17 | /** 18 | * Class UserLoginForm 19 | * @package app\models 20 | */ 21 | class UserLoginForm extends Model 22 | { 23 | /** 24 | * @var string 25 | */ 26 | public $email = ''; 27 | 28 | /** 29 | * @var string 30 | */ 31 | public $password = ''; 32 | 33 | /** 34 | * @var bool 35 | */ 36 | public $rememberMe = true; 37 | 38 | /** 39 | * @var bool 40 | */ 41 | private $_user = false; 42 | 43 | 44 | /** 45 | * @return array the validation rules. 46 | */ 47 | public function rules() 48 | { 49 | return [ 50 | [['email', 'password'], 'required'], 51 | ['rememberMe', 'boolean'], 52 | ['password', 'validatePassword'], 53 | ]; 54 | } 55 | 56 | /** 57 | * Validates the password. 58 | * This method serves as the inline validation for password. 59 | * 60 | * @param string $attribute the attribute currently being validated 61 | * @param array $params the additional name-value pairs given in the rule 62 | */ 63 | public function validatePassword($attribute, $params) 64 | { 65 | if (!$this->hasErrors()) { 66 | $user = $this->getUser(); 67 | 68 | if (!$user || !$user->validatePassword($this->password)) { 69 | $this->addError($attribute, \Yii::t('app', 'Incorrect email or password.')); 70 | } 71 | } 72 | } 73 | 74 | /** 75 | * Logs in a user using the provided username and password. 76 | * @return boolean whether the user is logged in successfully 77 | */ 78 | public function login() 79 | { 80 | if ($this->validate()) { 81 | return \Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600*24*30 : 0); 82 | } 83 | return false; 84 | } 85 | 86 | /** 87 | * Finds user by [[email]] 88 | * 89 | * @return User|null 90 | */ 91 | public function getUser() 92 | { 93 | if ($this->_user === false) { 94 | $this->_user = User::findByEmail($this->email); 95 | } 96 | 97 | return $this->_user; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /web/web/scss/material-dashboard/bootstrap/scss/_nav.scss: -------------------------------------------------------------------------------- 1 | // Base class 2 | // 3 | // Kickstart any navigation component with a set of style resets. Works with 4 | // `