├── Module.php
├── README.md
├── Survey.php
├── SurveyAsset.php
├── SurveyInterface.php
├── SurveyWidgetAsset.php
├── assets
├── css
│ ├── preloader.css
│ ├── preloader.css.map
│ ├── preloader.scss
│ ├── survey.css
│ ├── survey.css.map
│ └── survey.scss
└── js
│ ├── promise.min.js
│ ├── survey.js
│ └── survey.widget.js
├── composer.json
├── controllers
├── DefaultController.php
└── QuestionController.php
├── messages
├── en
│ └── survey.php
└── ru
│ └── survey.php
├── migrations
├── m181018_070730_create_table_survey.php
├── m181018_070730_create_table_survey_answer.php
├── m181018_070730_create_table_survey_question.php
├── m181018_070730_create_table_survey_stat.php
├── m181018_070730_create_table_survey_type.php
├── m181018_070730_create_table_survey_user_answer.php
├── m181018_070730_foreign_keys.php
└── m190918_224430_private_survey.php
├── models
├── Survey.php
├── SurveyAnswer.php
├── SurveyQuestion.php
├── SurveyStat.php
├── SurveyType.php
├── SurveyUserAnswer.php
└── search
│ ├── SurveySearch.php
│ └── SurveyStatSearch.php
├── views
├── answers
│ ├── 1.php
│ ├── 10.php
│ ├── 2.php
│ ├── 3.php
│ ├── 4.php
│ ├── 5.php
│ ├── 6.php
│ ├── 7.php
│ ├── 8.php
│ ├── 9.php
│ ├── _form.php
│ └── view
│ │ ├── 1.php
│ │ ├── 10.php
│ │ ├── 2.php
│ │ ├── 3.php
│ │ ├── 4.php
│ │ ├── 5.php
│ │ ├── 6.php
│ │ ├── 7.php
│ │ ├── 8.php
│ │ ├── 9.php
│ │ └── _form.php
├── default
│ ├── _form.php
│ ├── create.php
│ ├── index.php
│ ├── respondents.php
│ ├── restrictedUsers.php
│ ├── update.php
│ └── view.php
├── question
│ ├── _form.php
│ ├── _viewForm.php
│ └── cardView.php
└── widget
│ ├── answers
│ ├── 1.php
│ ├── 10.php
│ ├── 2.php
│ ├── 3.php
│ ├── 4.php
│ ├── 5.php
│ ├── 6.php
│ ├── 7.php
│ ├── 8.php
│ ├── 9.php
│ └── _form.php
│ ├── default
│ ├── closed.php
│ ├── index.php
│ ├── success.php
│ └── unavailable.php
│ └── question
│ └── _form.php
└── widgetControllers
├── DefaultController.php
└── QuestionController.php
/Module.php:
--------------------------------------------------------------------------------
1 | null,
23 | 'uploadsPath' => null,
24 | ];
25 |
26 | /**
27 | * @inheritdoc
28 | */
29 | public function init()
30 | {
31 |
32 | if (empty($this->controllerNamespace)) {
33 | $this->controllerNamespace = \Yii::$app->controllerNamespace === 'backend\controllers'
34 | ? 'onmotion\survey\controllers'
35 | : 'onmotion\survey\widgetControllers';
36 | }
37 |
38 | parent::init();
39 |
40 | if (empty($this->params['uploadsUrl'])) {
41 | throw new UserException("You must set uploadsUrl param in the config. Please see the documentation for more information.");
42 | } else {
43 | $this->params['uploadsUrl'] = rtrim($this->params['uploadsUrl'], '/');
44 | }
45 | if (empty($this->params['uploadsPath'])) {
46 | throw new UserException("You must set uploadsPath param in the config. Please see the documentation for more information.");
47 | } else {
48 | $this->params['uploadsPath'] = FileHelper::normalizePath($this->params['uploadsPath']);
49 | }
50 |
51 | $this->userClass = \Yii::$app->user->identityClass;
52 |
53 | \Yii::setAlias('@surveyRoot', __DIR__);
54 |
55 | // set up i8n
56 | if (empty(\Yii::$app->i18n->translations['survey'])) {
57 | \Yii::$app->i18n->translations['survey'] = [
58 | 'class' => 'yii\i18n\PhpMessageSource',
59 | 'basePath' => '@surveyRoot/messages',
60 | ];
61 | }
62 |
63 | $view = \Yii::$app->getView();
64 | SurveyAsset::register($view);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | Survey module for Yii2 application
3 | --
4 |
5 | [](https://packagist.org/packages/onmotion/yii2-survey)
6 | [](https://packagist.org/packages/onmotion/yii2-survey)
7 | [](https://packagist.org/packages/onmotion/yii2-survey)
8 | [](https://packagist.org/packages/onmotion/yii2-survey)
9 |
10 |
11 | >! Note: the module under active developing, so it may have vary errors and unstable work.
12 | > Highly appreciate your PR.
13 |
14 | 
15 |
16 |
17 | Installation
18 | --
19 |
20 | * Just run:
21 |
22 | composer require onmotion/yii2-survey
23 |
24 | or add
25 |
26 | "onmotion/yii2-survey": "*"
27 |
28 | to the require section of your composer.json file.
29 |
30 | * apply migration:
31 |
32 |
33 | ```sh
34 | php yii migrate --migrationPath=@vendor/onmotion/yii2-survey/migrations
35 | ```
36 |
37 | * Define module to your config:
38 |
39 | ```php
40 | 'modules' => [
41 | //...
42 | 'survey' => [
43 | 'class' => '\onmotion\survey\Module',
44 | 'params' => [
45 | 'uploadsUrl' => 'http://advanced-frontend.lh/uploads/survey/', // full URL of the folder where the images will be uploaded.
46 | // 'uploadsUrl' => '/uploads/survey/', // or for basic
47 | 'uploadsPath' => '@frontend/web/uploads/survey/', // absolute path to the folder where images will be saved.
48 | ],
49 | // 'as access' => [
50 | // 'class' => AccessControl::class,
51 | // 'except' => ['default/done'],
52 | // 'only' => ['default*'],
53 | // 'rules' => [
54 | // [
55 | // 'allow' => true,
56 | // 'roles' => ['survey'],
57 | // ],
58 | // ],
59 | // ],
60 | ],
61 | //...
62 | ]
63 | ```
64 |
65 | don't forget change your own params.
66 |
67 | Usage
68 | --
69 |
70 | If you are using the Yii basic template, you must manually define `$controllerNamespace` for module.
71 |
72 | *onmotion\survey\controllers* - backend (admin/create/edit surveys)
73 |
74 | *onmotion\survey\widgetControllers* - default (for widget)
75 |
76 | Now go to `/survey` in your backend and create a survey.
77 |
78 | 
79 |
80 | After that you can select Survey entities and show it for user, for example:
81 |
82 | ```php
83 | echo \onmotion\survey\Survey::widget([
84 | 'surveyId' => 1
85 | ]);
86 | ```
87 |
88 | 
89 |
90 | Admin:
91 |
92 | 
93 |
94 | 
--------------------------------------------------------------------------------
/Survey.php:
--------------------------------------------------------------------------------
1 | i18n->translations['survey'])) {
26 | \Yii::$app->i18n->translations['survey'] = [
27 | 'class' => 'yii\i18n\PhpMessageSource',
28 | 'basePath' => '@surveyRoot/messages',
29 | ];
30 | }
31 |
32 | \Yii::setAlias('@surveyRoot', __DIR__);
33 |
34 | parent::init();
35 | }
36 |
37 | public function getViewPath()
38 | {
39 | return \Yii::getAlias('@surveyRoot/views');
40 | }
41 |
42 | public function beforeRun()
43 | {
44 | // $assignedModel = SurveyStat::getAssignedUserStat(\Yii::$app->user->getId(), $this->surveyId);
45 | // if (empty($assignedModel)) {
46 | // throw new ForbiddenHttpException();
47 | // }
48 | return parent::beforeRun();
49 | }
50 |
51 | public function run()
52 | {
53 | $view = $this->getView();
54 | SurveyWidgetAsset::register($view);
55 |
56 | $survey = $this->findModel($this->surveyId);
57 | if (!$survey || !$survey->isAccessibleByCurrentUser) {
58 | return $this->renderUnavailable();
59 | }
60 |
61 | $status = $survey->getStatus();
62 | if ($status !== 'active') {
63 | return $this->renderClosed();
64 | }
65 |
66 | $assignedModel = SurveyStat::getAssignedUserStat(\Yii::$app->user->getId(), $this->surveyId);
67 | if (empty($assignedModel)) {
68 | SurveyStat::assignUser(\Yii::$app->user->getId(), $this->surveyId);
69 | $assignedModel = SurveyStat::getAssignedUserStat(\Yii::$app->user->getId(), $this->surveyId);
70 | } else {
71 | // if ($assignedModel->survey_stat_is_done){
72 | // return $this->renderClosed();
73 | // }
74 | }
75 |
76 |
77 | if ($assignedModel->survey_stat_started_at === null) {
78 | $assignedModel->survey_stat_started_at = new Expression('NOW()');
79 | $assignedModel->save(false);
80 | }
81 |
82 | return $this->renderSurvey($this->surveyId, $assignedModel);
83 | }
84 |
85 | private function renderClosed()
86 | {
87 | echo $this->render('widget/default/closed');
88 | }
89 |
90 | private function renderUnavailable()
91 | {
92 | echo $this->render('widget/default/unavailable');
93 | }
94 |
95 | private function renderSurvey($id, $stat)
96 | {
97 | $survey = $this->findModel($id);
98 | echo $this->render('widget/default/index', ['survey' => $survey, 'stat' => $stat]);
99 | }
100 |
101 | protected function findModel($id)
102 | {
103 | if (($model = \onmotion\survey\models\Survey::findOne($id)) !== null) {
104 | return $model;
105 | } else {
106 | throw new NotFoundHttpException('The requested page does not exist.');
107 | }
108 | }
109 | }
--------------------------------------------------------------------------------
/SurveyAsset.php:
--------------------------------------------------------------------------------
1 | sourcePath = __DIR__ . '/assets';
20 | parent::init();
21 | }
22 |
23 | public $publishOptions = [
24 | 'forceCopy' => YII_ENV_DEV //dev
25 | ];
26 |
27 | public $css = [
28 | 'css/survey.css',
29 | 'css/preloader.css',
30 | ];
31 | public $js = [
32 | 'js/survey.js',
33 | ];
34 | public $depends = [
35 | 'yii\web\YiiAsset',
36 | ];
37 | }
--------------------------------------------------------------------------------
/SurveyInterface.php:
--------------------------------------------------------------------------------
1 | sourcePath = __DIR__ . '/assets';
20 | parent::init();
21 | }
22 |
23 | public $publishOptions = [
24 | 'forceCopy' => YII_ENV_DEV //dev
25 | ];
26 |
27 | public $css = [
28 | 'css/survey.css',
29 | 'css/preloader.css',
30 | ];
31 | public $js = [
32 | 'js/promise.min.js',
33 | 'js/survey.widget.js',
34 | ];
35 | public $depends = [
36 | 'yii\web\YiiAsset',
37 | ];
38 | }
--------------------------------------------------------------------------------
/assets/css/preloader.css:
--------------------------------------------------------------------------------
1 | .preloader{width:100%;height:100%;position:absolute;left:0;top:0;background:rgba(255,255,255,0.6);z-index:100}.cssload-spin-box{position:absolute;margin:auto;left:0;top:0;bottom:0;right:0;width:15px;height:15px;border-radius:100%;box-shadow:15px 15px #4f4d49,-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf;-o-box-shadow:15px 15px #4f4d49,-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf;-ms-box-shadow:15px 15px #4f4d49,-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf;-webkit-box-shadow:15px 15px #4f4d49,-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf;-moz-box-shadow:15px 15px #4f4d49,-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf;animation:cssload-spin ease infinite 4.6s;-o-animation:cssload-spin ease infinite 4.6s;-ms-animation:cssload-spin ease infinite 4.6s;-webkit-animation:cssload-spin ease infinite 4.6s;-moz-animation:cssload-spin ease infinite 4.6s}@keyframes cssload-spin{0%,
2 | 100%{-webkit-box-shadow:15px 15px #4f4d49,-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf;box-shadow:15px 15px #4f4d49,-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf}25%{-webkit-box-shadow:-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf,15px 15px #4f4d49;box-shadow:-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf,15px 15px #4f4d49}50%{-webkit-box-shadow:-15px -15px #4f4d49,15px -15px #dfdfdf,15px 15px #4f4d49,-15px 15px #dfdfdf;box-shadow:-15px -15px #4f4d49,15px -15px #dfdfdf,15px 15px #4f4d49,-15px 15px #dfdfdf}75%{-webkit-box-shadow:15px -15px #dfdfdf, 15px 15px #4f4d49, -15px 15px #dfdfdf, -15px -15px #4f4d49;box-shadow:15px -15px #dfdfdf, 15px 15px #4f4d49, -15px 15px #dfdfdf, -15px -15px #4f4d49}}@-webkit-keyframes cssload-spin{0%,
3 | 100%{-webkit-box-shadow:15px 15px #4f4d49,-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf;box-shadow:15px 15px #4f4d49,-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf}25%{-webkit-box-shadow:-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf,15px 15px #4f4d49;box-shadow:-15px 15px #dfdfdf,-15px -15px #4f4d49,15px -15px #dfdfdf,15px 15px #4f4d49}50%{-webkit-box-shadow:-15px -15px #4f4d49,15px -15px #dfdfdf,15px 15px #4f4d49,-15px 15px #dfdfdf;box-shadow:-15px -15px #4f4d49,15px -15px #dfdfdf,15px 15px #4f4d49,-15px 15px #dfdfdf}75%{-webkit-box-shadow:15px -15px #dfdfdf, 15px 15px #4f4d49, -15px 15px #dfdfdf, -15px -15px #4f4d49;box-shadow:15px -15px #dfdfdf, 15px 15px #4f4d49, -15px 15px #dfdfdf, -15px -15px #4f4d49}}
4 |
--------------------------------------------------------------------------------
/assets/css/preloader.css.map:
--------------------------------------------------------------------------------
1 | {
2 | "version": 3,
3 | "mappings": "AAAA,UAAU;EACN,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,QAAQ,EAAE,QAAQ;EAClB,IAAI,EAAE,CAAC;EACP,GAAG,EAAE,CAAC;EACN,UAAU,EAAE,wBAAwB;EACpC,OAAO,EAAE,GAAG;;AAGhB,iBAAkB;EACd,QAAQ,EAAE,QAAQ;EAClB,MAAM,EAAE,IAAI;EACZ,IAAI,EAAE,CAAC;EACP,GAAG,EAAE,CAAC;EACN,MAAM,EAAE,CAAC;EACT,KAAK,EAAE,CAAC;EACR,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,aAAa,EAAE,IAAI;EACnB,UAAU,EAAE,8EAA4G;EACxH,aAAa,EAAE,8EAA4G;EAC3H,cAAc,EAAE,8EAA4G;EAC5H,kBAAkB,EAAE,8EAA4G;EAChI,eAAe,EAAE,8EAA4G;EAC7H,SAAS,EAAE,+BAA+B;EAC1C,YAAY,EAAE,+BAA+B;EAC7C,aAAa,EAAE,+BAA+B;EAC9C,iBAAiB,EAAE,+BAA+B;EAClD,cAAc,EAAE,+BAA+B;;AAInD,uBAcC;EAbG;QACK;IACD,UAAU,EAAE,8EAA4G;EAE5H,GAAI;IACA,UAAU,EAAE,8EAA4G;EAE5H,GAAI;IACA,UAAU,EAAE,8EAA4G;EAE5H,GAAI;IACA,UAAU,EAAE,8EAA8E;AAIlG,0BAcC;EAbG;QACK;IACD,UAAU,EAAE,8EAA4G;EAE5H,GAAI;IACA,UAAU,EAAE,8EAA4G;EAE5H,GAAI;IACA,UAAU,EAAE,8EAA4G;EAE5H,GAAI;IACA,UAAU,EAAE,8EAA8E;AAIlG,2BAcC;EAbG;QACK;IACD,UAAU,EAAE,8EAA4G;EAE5H,GAAI;IACA,UAAU,EAAE,8EAA4G;EAE5H,GAAI;IACA,UAAU,EAAE,8EAA4G;EAE5H,GAAI;IACA,UAAU,EAAE,8EAA8E;AAIlG,+BAcC;EAbG;QACK;IACD,UAAU,EAAE,8EAA4G;EAE5H,GAAI;IACA,UAAU,EAAE,8EAA4G;EAE5H,GAAI;IACA,UAAU,EAAE,8EAA4G;EAE5H,GAAI;IACA,UAAU,EAAE,8EAA8E;AAIlG,4BAcC;EAbG;QACK;IACD,UAAU,EAAE,8EAA4G;EAE5H,GAAI;IACA,UAAU,EAAE,8EAA4G;EAE5H,GAAI;IACA,UAAU,EAAE,8EAA4G;EAE5H,GAAI;IACA,UAAU,EAAE,8EAA8E",
4 | "sources": ["preloader.scss"],
5 | "names": [],
6 | "file": "preloader.css"
7 | }
8 |
--------------------------------------------------------------------------------
/assets/css/preloader.scss:
--------------------------------------------------------------------------------
1 | .preloader{
2 | width: 100%;
3 | height: 100%;
4 | position: absolute;
5 | left: 0;
6 | top: 0;
7 | background: rgba(255, 255, 255, 0.6);
8 | z-index: 100;
9 | }
10 |
11 | .cssload-spin-box {
12 | position: absolute;
13 | margin: auto;
14 | left: 0;
15 | top: 0;
16 | bottom: 0;
17 | right: 0;
18 | width: 15px;
19 | height: 15px;
20 | border-radius: 100%;
21 | box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223);
22 | -o-box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223);
23 | -ms-box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223);
24 | -webkit-box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223);
25 | -moz-box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223);
26 | animation: cssload-spin ease infinite 4.6s;
27 | -o-animation: cssload-spin ease infinite 4.6s;
28 | -ms-animation: cssload-spin ease infinite 4.6s;
29 | -webkit-animation: cssload-spin ease infinite 4.6s;
30 | -moz-animation: cssload-spin ease infinite 4.6s;
31 | }
32 |
33 |
34 | @keyframes cssload-spin {
35 | 0%,
36 | 100% {
37 | box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223);
38 | }
39 | 25% {
40 | box-shadow: -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73);
41 | }
42 | 50% {
43 | box-shadow: -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223);
44 | }
45 | 75% {
46 | box-shadow: 15px -15px #dfdfdf, 15px 15px #4f4d49, -15px 15px #dfdfdf, -15px -15px #4f4d49;
47 | }
48 | }
49 |
50 | @-o-keyframes cssload-spin {
51 | 0%,
52 | 100% {
53 | box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223);
54 | }
55 | 25% {
56 | box-shadow: -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73);
57 | }
58 | 50% {
59 | box-shadow: -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223);
60 | }
61 | 75% {
62 | box-shadow: 15px -15px #dfdfdf, 15px 15px #4f4d49, -15px 15px #dfdfdf, -15px -15px #4f4d49;
63 | }
64 | }
65 |
66 | @-ms-keyframes cssload-spin {
67 | 0%,
68 | 100% {
69 | box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223);
70 | }
71 | 25% {
72 | box-shadow: -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73);
73 | }
74 | 50% {
75 | box-shadow: -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223);
76 | }
77 | 75% {
78 | box-shadow: 15px -15px #dfdfdf, 15px 15px #4f4d49, -15px 15px #dfdfdf, -15px -15px #4f4d49;
79 | }
80 | }
81 |
82 | @-webkit-keyframes cssload-spin {
83 | 0%,
84 | 100% {
85 | box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223);
86 | }
87 | 25% {
88 | box-shadow: -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73);
89 | }
90 | 50% {
91 | box-shadow: -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223);
92 | }
93 | 75% {
94 | box-shadow: 15px -15px #dfdfdf, 15px 15px #4f4d49, -15px 15px #dfdfdf, -15px -15px #4f4d49;
95 | }
96 | }
97 |
98 | @-moz-keyframes cssload-spin {
99 | 0%,
100 | 100% {
101 | box-shadow: 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223);
102 | }
103 | 25% {
104 | box-shadow: -15px 15px rgb(223,223,223), -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73);
105 | }
106 | 50% {
107 | box-shadow: -15px -15px rgb(79,77,73), 15px -15px rgb(223,223,223), 15px 15px rgb(79,77,73), -15px 15px rgb(223,223,223);
108 | }
109 | 75% {
110 | box-shadow: 15px -15px #dfdfdf, 15px 15px #4f4d49, -15px 15px #dfdfdf, -15px -15px #4f4d49;
111 | }
112 | }
--------------------------------------------------------------------------------
/assets/css/survey.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sourceRoot":"","sources":["survey.scss"],"names":[],"mappings":"AAIA;EAEE;EACA;;;AAGF;EACE;;;AAIA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;EACA;;AAEA;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;;AAIJ;EACE;EACA;;AAEA;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;;AAIJ;EACE;EACA;;AAEA;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;;AAIJ;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;;;AAQJ;EACE;;;AAMJ;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAIA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAIJ;EACE;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE,kBA7KS;EA8KT;EACA;;AAEA;EACE;EACA;;AAIJ;EACE;;AAGF;EACE;;AAEA;EACE;;AAKJ;EACE;;AAEA;EACE;EACA;EAEA;;AAEA;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;;AAIJ;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;;AAIJ;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;;AAIJ;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAGF;EACE;EACA;EACA;;AAKN;EAME;;AALA;EACE;EACA;;AAKF;EACE;;AAGF;EACE;;AAGF;EACE,OAjSS;EAkST;EACA;;AAGF;EACE;;AAIJ;EACE;;AAGF;EACE;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAMN;EACE;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;;AAIJ;EACE;;AAEA;EACE;;AAIJ;EACE;;AAEA;EACE;EACA;;AAKJ;EACE;EACA;;AAEA;EACE;;AAKN;EAEE;EACA;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;;;AAIJ;EACE;EACA;;;AAIA;EACE;;;AAKF;EACE;;AAGF;EACE;;AAIF;EACE;;AAGF;EACE;EACA;;;AAIJ;EACE;;AAEA;EACE;;AAGF;EACE;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAIJ;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAKN;EACE;;AAKN;EACE;;;AAOF;EACE;;;AAKF;EACE;;AAEA;EACE;EACA;;AAIJ;EACE;;AAEA;EACE;;;AAKN;EACE,YA/jBa;EAgkBb;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;;AAQN;EACE;;AAGF;EACE;EACA;;;AAIJ;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;AAGF;EACE;;;AAMF;AAAA;AAAA;AAAA;EAEE;;AAEA;AAAA;AAAA;AAAA;EACE;;AAGF;AAAA;AAAA;AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;AAAA;AAAA;AAAA;EACE;;;AAON;EACE;;AAEA;EACE;;AAGE;EACE;EACA;;;AASN;EACE;;;AAMJ;EACE;;AAGF;EACE;EACA;;AAEA;EACE;;AAGF;EACE;EACA;EACA;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;;AAMR;EACE;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;;AAKF;EACE;EACA;EACA,YAtxBa;EAuxBb;;AAEA;EACE;EACA;;AAEA;EACE;;AAGF;EACE;EACA;EACA;;AAKF;EACE;EACA;EACA;;AAEA;EACE;;AAMR;EACE;;AAEA;EACE;;AAOA;EACE;EACA;EACA;;AAEA;EACE;;AAIA;EACE;EACA;;AAMR;EACE;;AAEA;EACE;;AAIJ;EACE;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;EACA;;AAEA;EACE;;AAIJ;EACE;EACA;;AAGF;EACE;;AAGF;EACE;EACA;EACA;EACA;;AAIF;EACE;;AAIJ;EACE;;AAGF;EACE;EACA;;;AAKN;EACE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAWA;EACE;EACA;;AAKJ;EACE;EACA;;AAEA;EACE;EACA;;AAEA;EACE;;AAKN;EACE;;;AAKF;EACE;;;AAIJ;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAOF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAIA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;;;AAIJ;EACE;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAKA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;;;AAIJ;EACE;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAKJ;EACE;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;;AAGF;EACE;EACA;EACA;;AAGF;EACE;;AAGF;EACE;;;AAKJ;EACE;;;AAKE;EACE;;AAEA;EACE;EACA;;AAGF;EACE;;AAIJ;EACE;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;EACA;;AAEA;EACE;EACA;;AAIJ;EACE;EACA;;AAGF;EACE;EACA;EACA;;AAGF;EACE;EACA;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAMN;EAIQ;IACE;IACA;IACA;;;AAOV;EACE","file":"survey.css"}
--------------------------------------------------------------------------------
/assets/js/promise.min.js:
--------------------------------------------------------------------------------
1 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.Promise=t()}(this,function(){"use strict";function e(){}function t(e,t){for(;3===e._state;)e=e._value;0!==e._state?(e._handled=!0,f._immediateFn(function(){var i=1===e._state?t.onFulfilled:t.onRejected;if(null!==i){var r;try{r=i(e._value)}catch(e){return void o(t.promise,e)}n(t.promise,r)}else(1===e._state?n:o)(t.promise,e._value)})):e._deferreds.push(t)}function n(e,t){try{if(t===e)throw new TypeError("A promise cannot be resolved with itself.");if(t&&("object"==typeof t||"function"==typeof t)){var n=t.then;if(t instanceof f)return e._state=3,e._value=t,void i(e);if("function"==typeof n)return void r(function(e,t){return function(){e.apply(t,arguments)}}(n,t),e)}e._state=1,e._value=t,i(e)}catch(t){o(e,t)}}function o(e,t){e._state=2,e._value=t,i(e)}function i(e){2===e._state&&0===e._deferreds.length&&f._immediateFn(function(){e._handled||f._unhandledRejectionFn(e._value)});for(var n=0,o=e._deferreds.length;o>n;n++)t(e,e._deferreds[n]);e._deferreds=null}function r(e,t){var i=!1;try{e(function(e){i||(i=!0,n(t,e))},function(e){i||(i=!0,o(t,e))})}catch(e){if(i)return;i=!0,o(t,e)}}function f(e){if(!(this instanceof f))throw new TypeError("Promises must be constructed via new");if("function"!=typeof e)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=void 0,this._deferreds=[],r(e,this)}var u=setTimeout,c=f.prototype;return c.catch=function(e){return this.then(null,e)},c.then=function(n,o){var i=new this.constructor(e);return t(this,new function(e,t,n){this.onFulfilled="function"==typeof e?e:null,this.onRejected="function"==typeof t?t:null,this.promise=n}(n,o,i)),i},f.all=function(e){return new f(function(t,n){function o(e,f){try{if(f&&("object"==typeof f||"function"==typeof f)){var u=f.then;if("function"==typeof u)return void u.call(f,function(t){o(e,t)},n)}i[e]=f,0==--r&&t(i)}catch(e){n(e)}}if(!e||void 0===e.length)throw new TypeError("Promise.all accepts an array");var i=Array.prototype.slice.call(e);if(0===i.length)return t([]);for(var r=i.length,f=0;i.length>f;f++)o(f,i[f])})},f.resolve=function(e){return e&&"object"==typeof e&&e.constructor===f?e:new f(function(t){t(e)})},f.reject=function(e){return new f(function(t,n){n(e)})},f.race=function(e){return new f(function(t,n){for(var o=0,i=e.length;i>o;o++)e[o].then(t,n)})},f._immediateFn="function"==typeof setImmediate&&function(e){setImmediate(e)}||function(e){u(e,0)},f._unhandledRejectionFn=function(e){void 0!==console&&console&&console.warn("Possible Unhandled Promise Rejection:",e)},f});
--------------------------------------------------------------------------------
/assets/js/survey.js:
--------------------------------------------------------------------------------
1 | ;(function ($) {
2 | "use strict";
3 |
4 | /**
5 | *
6 | */
7 | function Survey() {
8 |
9 | $(document).on('pjax:end', function (e, contents, options) {
10 | console.log(e);
11 | if (e.target.id === 'survey-questions-append') {
12 | var appendContainer = $('#survey-questions-append').find('.survey-question-pjax-container');
13 | appendContainer.appendTo('#survey-questions');
14 | }
15 | });
16 |
17 | $(document).on('pjax:timeout', function (event) {
18 | // Prevent default timeout redirection behavior
19 | console.log(event);
20 | event.preventDefault();
21 | });
22 |
23 | $(document).on('pjax:error', function (event, xhr, textStatus, error, options) {
24 | console.log(event);
25 | event.preventDefault();
26 | });
27 |
28 |
29 | $(document).on('click', '.survey-question-submit, .user-assign-submit', pseudoSubmit);
30 |
31 | function pseudoSubmit(e) {
32 | e.preventDefault();
33 | var $this = $(this);
34 | var data = $this.data();
35 | var action = data.action;
36 | var $form = $this.closest('form');
37 | console.log($form);
38 | if ($form && action) {
39 | $form.attr('action', action).submit();
40 | } else {
41 | console.log('Error');
42 | }
43 | }
44 |
45 | $(document).on('click', '.checkbox-updatable', function (e) {
46 | var container = $(this).closest('[data-pjax-container]');
47 | container.find('.update-question-btn').click();
48 | });
49 |
50 | $(document).on('click', '.submit-on-click', function (e) {
51 | var container = $(this).closest('[data-pjax-container]');
52 | container.find('button[type=submit]').click();
53 | });
54 |
55 |
56 | async function submitAllForms() {
57 | var forms = [];
58 | var $body = $('body');
59 | $body.toggleClass('survey-loading');
60 | var btn = $(this).find('button');
61 | btn.prop('disabled', true);
62 | var defaultText = btn.data('default-text') || '';
63 | btn.html('');
64 | var allFormsIsValid = true;
65 |
66 | $(document).find('form.form-inline').each(function (i, el) {
67 | forms.push($(el));
68 | });
69 |
70 | for (var item of forms) {
71 | try {
72 | await confirmForm(item);
73 | } catch (err) {
74 | allFormsIsValid = false;
75 | }
76 | }
77 |
78 | if (allFormsIsValid) {
79 | location.href = $('#save').data('action');
80 | } else {
81 | btn.prop('disabled', false);
82 | btn.html(defaultText);
83 | $body.toggleClass('survey-loading');
84 | }
85 | }
86 |
87 | $(document).on('click', '#save', submitAllForms);
88 |
89 | $(document).on('click', '.close-btn', function (e) {
90 | $(this).parent().toggleClass('opened');
91 | $('body').toggleClass('modal-open');
92 | });
93 |
94 | $(document).on('click', '.respondents-toggle', function (e) {
95 | $('#respondents-modal').toggleClass('opened');
96 | $('body').toggleClass('modal-open');
97 | });
98 |
99 | $(document).on('click', '.restricted-users-toggle', function (e) {
100 | $('#restricted-users-modal').toggleClass('opened');
101 | $('body').toggleClass('modal-open');
102 | });
103 |
104 |
105 | function confirmForm(form) {
106 | return new Promise((resolve, reject) => {
107 | var container = form.closest('[data-pjax-container]');
108 | form.submit();
109 | container.on('afterValidate', function (event, messages, errorAttributes) {
110 | if (errorAttributes.length > 0) {
111 | reject(messages);
112 | }
113 | });
114 | container.on('pjax:end', function (e) {
115 | console.log(e);
116 | resolve(e);
117 | });
118 | container.on('pjax:error', function (e) {
119 | console.log(e);
120 | reject(e);
121 | });
122 | });
123 | }
124 |
125 |
126 | var showProgress;
127 | showProgress = function showProgress(container) {
128 | try {
129 | container.prepend('
');
130 | } catch (err) {
131 | console.log(e.message);
132 | }
133 | $('.preloader').fadeIn();
134 | };
135 |
136 | var hideProgress;
137 | (hideProgress = function hideProgress(container = null) {
138 | try {
139 | if (container !== null) {
140 | $(container).find('.preloader').fadeOut(500, function () {
141 | $(this).remove();
142 | });
143 | } else {
144 | $('.preloader').fadeOut(500, function () {
145 | $(this).remove();
146 | });
147 | }
148 | } catch (err) {
149 | console.log(e.message);
150 | }
151 | })();
152 |
153 | $(document).on('pjax:start', function (e) {
154 | if ((e.target.id).indexOf('survey-questions-pjax-') !== -1) {
155 | showProgress($('#' + e.target.id).find('.survey-block '));
156 | }
157 | });
158 |
159 | $(document).on('pjax:complete', function (e) {
160 | if ((e.target.id).indexOf('survey-questions-pjax-') !== -1 || (e.target.id === 'survey-questions-append')) {
161 | hideProgress($('#' + e.target.id));
162 | }
163 | });
164 | }
165 |
166 | $.fn['survey'] = function () {
167 | console.log('survey init');
168 | if (!$.data(this, 'plugin_Survey')) {
169 | return $.data(this, 'plugin_Survey',
170 | new Survey());
171 | }
172 | }
173 |
174 | })(window.jQuery);
--------------------------------------------------------------------------------
/assets/js/survey.widget.js:
--------------------------------------------------------------------------------
1 | ;(function ($) {
2 | "use strict";
3 |
4 | /**
5 | *
6 | */
7 | function SurveyWidget(options) {
8 |
9 | this.id = options.id || null;
10 |
11 | $(document).on('pjax:end', function (e, contents, options) {
12 | console.log(e);
13 | if (e.target.id === 'survey-questions-append') {
14 | var appendContainer = $('#survey-questions-append').find('.survey-question-pjax-container');
15 | appendContainer.appendTo('#survey-questions');
16 | }
17 | });
18 |
19 | $(document).on('pjax:timeout', function (event) {
20 | // Prevent default timeout redirection behavior
21 | console.log(event);
22 | event.preventDefault();
23 | });
24 |
25 | $(document).on('pjax:error', function (event, xhr, textStatus, error, options) {
26 | console.log(event);
27 | event.preventDefault();
28 | });
29 |
30 | var showProgress;
31 | showProgress = function showProgress(container) {
32 | try {
33 | container.prepend('');
34 | } catch (err) {
35 | console.log(e.message);
36 | }
37 | $('.preloader').fadeIn();
38 | };
39 |
40 | var hideProgress = function hideProgress(container) {
41 | container = container || null;
42 | try {
43 | if (container !== null) {
44 | $(container).find('.preloader').fadeOut(500, function () {
45 | $(this).remove();
46 | });
47 | } else {
48 | $('.preloader').fadeOut(500, function () {
49 | $(this).remove();
50 | });
51 | }
52 | } catch (err) {
53 | console.log(e.message);
54 | }
55 | };
56 | hideProgress();
57 |
58 | $(document).on('pjax:start', function (e) {
59 | if ((e.target.id).indexOf('survey-questions-pjax-') !== -1) {
60 | showProgress($('#' + e.target.id).find('.survey-block '));
61 | }
62 | });
63 |
64 | $(document).on('pjax:complete', function (e) {
65 | if ((e.target.id).indexOf('survey-questions-pjax-') !== -1 || (e.target.id === 'survey-questions-append')) {
66 | hideProgress($('#' + e.target.id));
67 | }
68 | });
69 |
70 |
71 | $(document).on('afterValidateAttribute', function (event, attribute, messages) {
72 | if (messages.length === 0) {
73 | var submitBtn = $(event.target).find('.btn-submit');
74 | // submitBtn.showUp();
75 | // console.log(submitBtn.showUp());
76 | }
77 | });
78 |
79 | function createModal() {
80 | $('html').append("\
81 | \
82 |
\
83 |
\
84 | \
88 |
\
89 |
\
90 | \
93 |
\
94 |
\
95 |
");
96 | }
97 |
98 | function removeModal() {
99 | $('#survey-modal').remove();
100 | }
101 |
102 | function confirmForm(form) {
103 | return new Promise(function(resolve, reject) {
104 | var container = form.closest('[data-pjax-container]');
105 | form.submit();
106 | container.off('afterValidate').on('afterValidate', function (event, messages, errorAttributes) {
107 | if (errorAttributes.length > 0) {
108 | reject(messages);
109 | } else {
110 | resolve(true);
111 | }
112 | });
113 |
114 | container.off('pjax:error').on('pjax:error', function (e) {
115 | // console.log(e);
116 | reject(e);
117 | });
118 | setTimeout(function() {
119 | resolve(true);
120 | }, 5000);
121 | });
122 |
123 | }
124 |
125 | var that = this;
126 |
127 | function submitAllForms() {
128 | var forms = [];
129 | var $body = $('body');
130 | $body.toggleClass('survey-loading');
131 | var btn = $(this);
132 | btn.prop('disabled', true);
133 | var defaultText = btn.data('default-text') || '';
134 | btn.html('');
135 | var allFormsIsValid = true;
136 | console.log(allFormsIsValid);
137 |
138 | $(document).find('form.question-form').each(function (i, el) {
139 | forms.push($(el));
140 | });
141 |
142 | var promises = [];
143 | for (var _i = 0; _i < forms.length; _i++) {
144 | var item = forms[_i];
145 | promises.push(confirmForm(item));
146 | }
147 |
148 | Promise.all(promises).then(function (resolve) {
149 | var csrfParam = $('meta[name="csrf-param"]').attr("content");
150 | var csrfToken = $('meta[name="csrf-token"]').attr("content");
151 | var data = {};
152 | data[csrfParam] = csrfToken;
153 | data.id = that.id;
154 | $.ajax({
155 | url: btn.data('action') || window.location.pathname,
156 | type: 'post',
157 | data: data,
158 | success: function success(response) {
159 | btn.remove();
160 | createModal();
161 |
162 | forms.forEach(f => {
163 | f.find(':input').prop('disabled', true);
164 | f.find('input[data-krajee-slider]').slider('disable');
165 | });
166 |
167 | var modal = $('#survey-modal');
168 | modal.find('.modal-header').html(response.title);
169 | modal.find('.modal-body').html(response.content);
170 | modal.find('.modal-footer').html(response.footer);
171 | modal.modal();
172 | },
173 | complete: function complete() {
174 | $body.toggleClass('survey-loading');
175 | },
176 | error: function error(err) {
177 | createModal();
178 | var modal = $('#survey-modal');
179 | modal.find('.modal-header').html(err.statusText);
180 | modal.find('.modal-body').html(err.responseText);
181 | modal.modal();
182 | }
183 | });
184 | }, function (reject) {
185 | btn.prop('disabled', false);
186 | btn.html(defaultText);
187 | $body.toggleClass('survey-loading');
188 | });
189 | }
190 |
191 | $(document).on('click', '#s-done', submitAllForms);
192 |
193 | }
194 |
195 |
196 | $.fn.showUp = function () {
197 | if (!this.hasClass('fadeIn')) {
198 | this.removeClass('hidden').addClass('fadeIn');
199 | }
200 | return this;
201 | };
202 |
203 | $.fn["surveyWidget"] = function() {
204 | var options =
205 | arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
206 |
207 | console.log("survey widget init");
208 | if (!$.data(this, "plugin_SurveyWidget")) {
209 | return $.data(this, "plugin_SurveyWidget", new SurveyWidget(options));
210 | }
211 | };
212 |
213 |
214 | })(window.jQuery);
215 |
216 |
217 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "onmotion/yii2-survey",
3 | "description": "survey module for Yii2 application",
4 | "type": "yii2-extension",
5 | "keywords": ["yii2","extension","module","widget", "survey", "polls"],
6 | "license": "MIT",
7 | "authors": [
8 | {
9 | "name": "Alexandr Kozhevnikov",
10 | "email": "onmotion1@gmail.com",
11 | "homepage": "http://kozhevnikov.me",
12 | "role": "Developer"
13 | }
14 | ],
15 | "require": {
16 | "php": ">=5.5.0",
17 | "yiisoft/yii2": ">=2.0.1",
18 | "cenotia/yii2-remote-modal": "^1.0",
19 | "kartik-v/yii2-dialog": "^1.0",
20 | "onmotion/yii2-widget-upload-crop": ">=0.5",
21 | "kartik-v/yii2-editable": "^1.7",
22 | "kartik-v/yii2-widget-datetimepicker": "^1.4",
23 | "vova07/yii2-imperavi-widget": "^2.0",
24 | "kartik-v/yii2-widget-select2": "^2.1",
25 | "yiisoft/yii2-imagine": "^2.1",
26 | "kartik-v/yii2-slider": "^1.3",
27 | "kartik-v/yii2-widget-datepicker": "^1.4",
28 | "kartik-v/yii2-helpers": "^1.3",
29 | "kartik-v/yii2-widget-typeahead": "^1.0"
30 | },
31 | "autoload": {
32 | "psr-4": {
33 | "onmotion\\survey\\": ""
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/controllers/QuestionController.php:
--------------------------------------------------------------------------------
1 | [
32 | 'class' => 'vova07\imperavi\actions\GetImagesAction',
33 | 'url' => $this->module->params['uploadsUrl'] . \Yii::$app->session->get('surveyUploadsSubpath', ''), // URL адрес папки где хранятся изображения.
34 | 'path' => $this->module->params['uploadsPath'] . \Yii::$app->session->get('surveyUploadsSubpath', ''), // Или абсолютный путь к папке с изображениями.
35 | 'options' => ['only' => ['*.jpg', '*.jpeg', '*.png', '*.gif', '*.ico']], // These options are by default.
36 | ],
37 | 'image-upload' => [
38 | 'class' => 'vova07\imperavi\actions\UploadFileAction',
39 | 'url' => $this->module->params['uploadsUrl'] . \Yii::$app->session->get('surveyUploadsSubpath', ''), // URL адрес папки где хранятся изображения.
40 | 'path' => $this->module->params['uploadsPath'] . \Yii::$app->session->get('surveyUploadsSubpath', ''), // Или абсолютный путь к папке с изображениями.
41 | ],
42 | 'files-get' => [
43 | 'class' => 'vova07\imperavi\actions\GetFilesAction',
44 | 'url' => $this->module->params['uploadsUrl'] . \Yii::$app->session->get('surveyUploadsSubpath', ''), // URL адрес папки где хранятся изображения.
45 | 'path' => $this->module->params['uploadsPath'] . \Yii::$app->session->get('surveyUploadsSubpath', ''), // Или абсолютный путь к папке с изображениями.
46 | ],
47 | 'file-upload' => [
48 | 'class' => 'vova07\imperavi\actions\UploadFileAction',
49 | 'url' => $this->module->params['uploadsUrl'] . \Yii::$app->session->get('surveyUploadsSubpath', ''), // URL адрес папки где хранятся изображения.
50 | 'path' => $this->module->params['uploadsPath'] . \Yii::$app->session->get('surveyUploadsSubpath', ''), // Или абсолютный путь к папке с изображениями.
51 | 'uploadOnlyImage' => false, // Для загрузки не только изображений.
52 | ],
53 |
54 | ];
55 | }
56 |
57 | public function actionCreate($id)
58 | {
59 | $survey = $this->findSurveyModel($id);
60 | $question = new SurveyQuestion();
61 | $question->loadDefaultValues();
62 | // $question->survey_question_name = \Yii::t('survey', 'New Question');
63 | $survey->link('questions', $question);
64 |
65 | for ($i = 1; $i <= 2; ++$i) {
66 | $question->link('answers', (new SurveyAnswer(['survey_answer_sort' => $i])));
67 | }
68 |
69 | return $this->renderAjax('_form', ['question' => $question]);
70 | }
71 |
72 | public function actionDelete($id)
73 | {
74 | $question = $this->findModel($id);
75 |
76 | if ($question->delete()) {
77 | return '';
78 | } else {
79 | throw new HttpException('500', 'unable to delete record');
80 | }
81 | }
82 |
83 | public function actionValidate($id)
84 | {
85 | $question = $this->findModel($id);
86 | $post = \Yii::$app->request->post();
87 | $action = ArrayHelper::getValue($post, "action");
88 | $result = [];
89 | \Yii::$app->response->format = Response::FORMAT_JSON;
90 |
91 | $questionIsChanged = false;
92 |
93 | $questionData = ArrayHelper::getValue($post, "SurveyQuestion.{$question->survey_question_id}");
94 | if (!empty($questionData) && $question->load($questionData, '')) {
95 | $isValid = $question->validate();
96 | $questionIsChanged = !empty($question->getDirtyAttributes());
97 | foreach ($question->getErrors() as $attribute => $errors) {
98 | $result["surveyquestion-{$question->survey_question_id}-{$attribute}"] = $errors;
99 | }
100 | if ($isValid) {
101 | $attrsForSave = $question->getAttributes(null, ['survey_question_type']);
102 | $attrs = array_keys($question->getDirtyAttributes(array_keys($attrsForSave)));
103 | $question->save(false, $attrs);
104 | }
105 | }
106 |
107 | $answersData = ArrayHelper::getValue($post, "SurveyAnswer.{$question->survey_question_id}");
108 |
109 | if (!empty($answersData)
110 | && (count($answersData) === count($question->answers))
111 | && Model::loadMultiple($question->answers, $answersData, '')) {
112 | foreach ($question->answers as $i => $model) {
113 | if (!$questionIsChanged || $action !== 'delete-answer') {
114 | $model->validate();
115 | foreach ($model->getErrors() as $attribute => $errors) {
116 | $result["surveyanswer-{$question->survey_question_id}-{$i}-{$attribute}"] = $errors;
117 | }
118 | }
119 | // $model->validate();
120 | $model->save();
121 | }
122 | }
123 |
124 | return $result;
125 | }
126 |
127 | public function actionUpdate($id)
128 | {
129 | $question = $this->findModel($id);
130 |
131 | $post = \Yii::$app->request->post();
132 |
133 | $questionData = ArrayHelper::getValue($post, "SurveyQuestion.{$question->survey_question_id}");
134 |
135 | $isTypeChanged = false;
136 | if (!empty($questionData) && $question->load($questionData, '') && $question->validate()) {
137 | $isTypeChanged = $question->isAttributeChanged('survey_question_type');
138 | if ($isTypeChanged) {
139 | $question->changeDefaultValuesOnTypeChange();
140 | }
141 | $question->save(false);
142 | }
143 |
144 | $answersData = ArrayHelper::getValue($post, "SurveyAnswer.{$question->survey_question_id}");
145 | if (!empty($answersData) && Model::loadMultiple($question->answers, $answersData, '') && !$isTypeChanged) {
146 | foreach ($question->answers as $answer) {
147 | $answer->save();
148 | }
149 | }
150 |
151 | $question->refresh();
152 |
153 | return $this->renderAjax('_form', ['question' => $question]);
154 | }
155 |
156 | public function actionEdit($id)
157 | {
158 | $question = $this->findModel($id);
159 | return $this->renderAjax('_form', ['question' => $question]);
160 | }
161 |
162 |
163 | public function actionAddAnswer($id, $after = null)
164 | {
165 | $question = $this->findModel($id);
166 | $answers = $question->answers;
167 | $lastAnswer = array_values(array_slice($answers, -1))[0];
168 |
169 | if (!isset($after)) {
170 | $sort = ArrayHelper::getValue($lastAnswer, 'survey_answer_sort', 0) + 1;
171 | } else {
172 | $pevAnswer = $answers[$after] ? $answers[$after] : null;
173 | $sort = ArrayHelper::getValue($pevAnswer, 'survey_answer_sort', 0) + 1;
174 |
175 | //moving all new answers forward
176 | SurveyAnswer::updateAll(['survey_answer_sort' => new Expression('survey_answer_sort+1')],
177 | ['AND', ['>=', 'survey_answer_sort', $sort], ['survey_answer_question_id' => $question->survey_question_id]]);
178 | }
179 |
180 | $question->link('answers', (new SurveyAnswer(['survey_answer_sort' => $sort])));
181 | //updated model
182 | $question = $this->findModel($id);
183 |
184 | return $this->renderAjax('_form', ['question' => $question]);
185 | }
186 |
187 | public function actionDeleteAnswer($id, $answer)
188 | {
189 | $question = $this->findModel($id);
190 | $answer = $question->answers[$answer];
191 | $answer->delete();
192 |
193 | //updated model
194 | $question = $this->findModel($id);
195 |
196 | return $this->renderAjax('_form', ['question' => $question]);
197 | }
198 |
199 | public function actionUpdateAndClose($id)
200 | {
201 | $question = $this->findModel($id);
202 |
203 | $post = \Yii::$app->request->post();
204 |
205 | $questionData = ArrayHelper::getValue($post, "SurveyQuestion.{$question->survey_question_id}");
206 | if (!empty($questionData) && $question->load($questionData, '')) {
207 | $question->save();
208 | }
209 |
210 | $answersData = ArrayHelper::getValue($post, "SurveyAnswer.{$question->survey_question_id}");
211 | if (!empty($answersData) && Model::loadMultiple($question->answers, $answersData, '')) {
212 | foreach ($question->answers as $answer) {
213 | $answer->save();
214 | }
215 | }
216 |
217 | return $this->renderAjax('cardView', ['question' => $question]);
218 | }
219 |
220 |
221 | protected function findModel($id)
222 | {
223 | if (($model = SurveyQuestion::findOne($id)) !== null) {
224 | return $model;
225 | } else {
226 | throw new NotFoundHttpException('The requested page does not exist.');
227 | }
228 | }
229 |
230 | protected function findSurveyModel($id)
231 | {
232 | if (($model = Survey::findOne($id)) !== null) {
233 | return $model;
234 | } else {
235 | throw new NotFoundHttpException('The requested page does not exist.');
236 | }
237 | }
238 |
239 | protected function findTypeModel($id)
240 | {
241 | if (($model = SurveyType::findOne($id)) !== null) {
242 | return $model;
243 | } else {
244 | throw new NotFoundHttpException('The requested page does not exist.');
245 | }
246 | }
247 | }
248 |
--------------------------------------------------------------------------------
/messages/en/survey.php:
--------------------------------------------------------------------------------
1 | 'Create new survey',
11 | ];
--------------------------------------------------------------------------------
/messages/ru/survey.php:
--------------------------------------------------------------------------------
1 | 'Добавление нового опроса',
12 | 'New Survey' => 'Новый Опрос',
13 | 'Created at' => 'Добавлен',
14 | 'Updated at' => 'Обновлен',
15 | 'Expired at' => 'Действует до',
16 | 'Question Type' => 'Тип вопроса',
17 | 'New Question' => 'Новый Вопрос',
18 | 'Add question' => 'Добавить вопрос',
19 | 'Save' => 'Сохранить',
20 | 'Can be skipped' => 'Может быть пропущен',
21 | 'Detailed description' => 'Подробное описание',
22 | 'Show detailed description' => 'Показывать подробное описание',
23 | 'Points' => 'Баллы',
24 | 'Score this question' => 'Оценивать этот вопрос',
25 | 'Type' => 'Тип',
26 | 'Description' => 'Описание',
27 | 'Answer' => 'Ответ',
28 | 'Question' => 'Вопрос',
29 | 'Enter an answer choice' => 'Введите вариант ответа',
30 | 'Comment' => 'Комментарий',
31 | 'Name' => 'Наименование',
32 | 'Closed' => 'Закрыт',
33 | 'Pinned' => 'Закреплен',
34 | 'Price' => 'Цена',
35 | 'Tags' => 'Теги',
36 | 'Current types are not compatible, all entered data will be deleted. Are you sure?' => 'Текущие типы несовместимы, все введенные данные будут удалены. Вы уверены?',
37 | 'Label' => 'Заголовок',
38 | 'Enter your answer here' => 'Введите свой ответ',
39 | 'Time to pass' => 'Время прохождения',
40 | 'Enter question name' => 'Введите вопрос',
41 | 'Were interviewed' => 'Прошли опрос',
42 | 'Respondents count' => 'Респондентов',
43 | 'Questions count' => 'Вопросов',
44 | 'Number of respondents' => 'Респондентов',
45 | 'Add respondents' => 'Добавить респондентов',
46 |
47 | 'Error' => 'Ошибка',
48 | 'Complete' => 'Завершено',
49 | 'An error has occurred' => 'Ошибка',
50 | 'Operation completed successfully' => 'Операция завершена успешно',
51 | 'Select...' => 'Выбрать',
52 | 'Done' => 'Готово',
53 | 'You must enter an answer' => 'Необходимо ввести ответ',
54 |
55 | 'Multiple choice' => 'Множественный выбор',
56 | 'One choise of list' => 'Один из списка',
57 | 'Dropdown' => 'Выпадающий список',
58 | 'Ranking' => 'Ранжирование',
59 | 'Slider' => 'Слайдер',
60 | 'Single textbox' => 'Одно текстовое поле',
61 | 'Multiple textboxes' => 'Несколько текстовых полей',
62 | 'Comment box' => 'Открытый ответ',
63 | 'Date/Time' => 'Дата/Время',
64 |
65 | 'Wallet Price' => 'В кошелек',
66 | 'Status Price' => 'В статус',
67 | ];
--------------------------------------------------------------------------------
/migrations/m181018_070730_create_table_survey.php:
--------------------------------------------------------------------------------
1 | db->driverName === 'mysql') {
11 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
12 | }
13 |
14 | $this->createTable('{{%survey}}', [
15 | 'survey_id' => $this->primaryKey()->unsigned(),
16 | 'survey_name' => $this->string(),
17 | 'survey_created_at' => $this->timestamp()->defaultExpression('CURRENT_TIMESTAMP'),
18 | 'survey_updated_at' => $this->timestamp(),
19 | 'survey_expired_at' => $this->timestamp(),
20 | 'survey_is_pinned' => $this->boolean()->defaultValue('0'),
21 | 'survey_is_closed' => $this->boolean()->defaultValue('0'),
22 | 'survey_tags' => $this->string(),
23 | 'survey_image' => $this->string(),
24 | 'survey_created_by' => $this->integer(),
25 | 'survey_wallet' => $this->integer()->unsigned(),
26 | 'survey_status' => $this->integer()->unsigned(),
27 | 'survey_descr' => $this->text(),
28 | 'survey_time_to_pass' => $this->smallInteger()->unsigned(),
29 | 'survey_badge_id' => $this->integer()->unsigned(),
30 | ], $tableOptions);
31 |
32 | $this->createIndex('fk_survey_created_by_idx', '{{%survey}}', 'survey_created_by');
33 | }
34 |
35 | public function down()
36 | {
37 | $this->dropTable('{{%survey}}');
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/migrations/m181018_070730_create_table_survey_answer.php:
--------------------------------------------------------------------------------
1 | db->driverName === 'mysql') {
11 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
12 | }
13 |
14 | $this->createTable('{{%survey_answer}}', [
15 | 'survey_answer_id' => $this->bigPrimaryKey()->unsigned(),
16 | 'survey_answer_question_id' => $this->integer()->unsigned(),
17 | 'survey_answer_name' => $this->string(),
18 | 'survey_answer_descr' => $this->text(),
19 | 'survey_answer_class' => $this->string(),
20 | 'survey_answer_comment' => $this->string(),
21 | 'survey_answer_sort' => $this->integer(),
22 | 'survey_answer_points' => $this->integer()->defaultValue('0'),
23 | 'survey_answer_show_descr' => $this->boolean()->defaultValue('0'),
24 | ], $tableOptions);
25 |
26 | $this->createIndex('fk_survey_answer_to_question_idx', '{{%survey_answer}}', 'survey_answer_question_id');
27 | }
28 |
29 | public function down()
30 | {
31 | $this->dropTable('{{%survey_answer}}');
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/migrations/m181018_070730_create_table_survey_question.php:
--------------------------------------------------------------------------------
1 | db->driverName === 'mysql') {
11 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
12 | }
13 |
14 | $this->createTable('{{%survey_question}}', [
15 | 'survey_question_id' => $this->primaryKey()->unsigned(),
16 | 'survey_question_name' => $this->string(),
17 | 'survey_question_descr' => $this->text(),
18 | 'survey_question_type' => $this->tinyInteger()->unsigned(),
19 | 'survey_question_survey_id' => $this->integer()->unsigned(),
20 | 'survey_question_can_skip' => $this->boolean()->defaultValue('0'),
21 | 'survey_question_show_descr' => $this->boolean()->defaultValue('0'),
22 | 'survey_question_is_scorable' => $this->boolean()->defaultValue('0'),
23 | ], $tableOptions);
24 |
25 | $this->createIndex('fk_survey_question_to_survey_idx', '{{%survey_question}}', 'survey_question_survey_id');
26 | $this->createIndex('fk_survey_question_to_type_idx', '{{%survey_question}}', 'survey_question_type');
27 | }
28 |
29 | public function down()
30 | {
31 | $this->dropTable('{{%survey_question}}');
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/migrations/m181018_070730_create_table_survey_stat.php:
--------------------------------------------------------------------------------
1 | db->driverName === 'mysql') {
11 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
12 | }
13 |
14 | $this->createTable('{{%survey_stat}}', [
15 | 'survey_stat_id' => $this->primaryKey()->unsigned(),
16 | 'survey_stat_survey_id' => $this->integer()->unsigned(),
17 | 'survey_stat_user_id' => $this->integer(),
18 | 'survey_stat_assigned_at' => $this->timestamp(),
19 | 'survey_stat_started_at' => $this->timestamp(),
20 | 'survey_stat_updated_at' => $this->timestamp(),
21 | 'survey_stat_ended_at' => $this->timestamp(),
22 | 'survey_stat_ip' => $this->string(),
23 | 'survey_stat_is_done' => $this->boolean()->defaultValue('0'),
24 | 'survey_stat_hash' => $this->char(32),
25 | ], $tableOptions);
26 |
27 | $this->createIndex('fk_sas_user_idx', '{{%survey_stat}}', 'survey_stat_user_id');
28 | $this->createIndex('survey_stat_hash_UNIQUE', '{{%survey_stat}}', 'survey_stat_hash', true);
29 | $this->createIndex('fk_stat_to_survey_idx', '{{%survey_stat}}', 'survey_stat_survey_id');
30 | }
31 |
32 | public function down()
33 | {
34 | $this->dropTable('{{%survey_stat}}');
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/migrations/m181018_070730_create_table_survey_type.php:
--------------------------------------------------------------------------------
1 | db->driverName === 'mysql') {
11 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
12 | }
13 |
14 | $this->createTable('{{%survey_type}}', [
15 | 'survey_type_id' => $this->tinyInteger()->unsigned()->notNull()->append('AUTO_INCREMENT PRIMARY KEY'),
16 | 'survey_type_name' => $this->string(),
17 | 'survey_type_descr' => $this->string(),
18 | ], $tableOptions);
19 |
20 | $this->batchInsert('{{%survey_type}}', ['survey_type_name', 'survey_type_descr'], [
21 | ['Multiple choice', 'Ask your respondent to choose multiple answers from your list of answer choices.'],
22 | ['One choise of list', 'Ask your respondent to choose one answer from your list of answer choices.'],
23 | ['Dropdown', 'Provide a dropdown list of answer choices for respondents to choose from.'],
24 | ['Ranking', 'Ask respondents to rank a list of options in the order they prefer using numeric dropdown menus.'],
25 | ['Slider', 'Ask respondents to rate an item or question by dragging an interactive slider.'],
26 | ['Single textbox', 'Add a single textbox to your survey when you want respondents to write in a short text or numerical answer to your question.'],
27 | ['Multiple textboxes', 'Add multiple textboxes to your survey when you want respondents to write in more than one short text or numerical answer to your question.'],
28 | ['Comment box', 'Use the comment or essay box to collect open-ended, written feedback from respondents.'],
29 | ['Date/Time', 'Ask respondents to enter a specific date and/or time.'],
30 | ['Calendar', 'Ask respondents to choose better date/time for a meeting.']
31 | ]);
32 |
33 | }
34 |
35 | public function down()
36 | {
37 | $this->dropTable('{{%survey_type}}');
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/migrations/m181018_070730_create_table_survey_user_answer.php:
--------------------------------------------------------------------------------
1 | db->driverName === 'mysql') {
11 | $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
12 | }
13 |
14 | $this->createTable('{{%survey_user_answer}}', [
15 | 'survey_user_answer_id' => $this->primaryKey()->unsigned(),
16 | 'survey_user_answer_user_id' => $this->integer(),
17 | 'survey_user_answer_survey_id' => $this->integer()->unsigned(),
18 | 'survey_user_answer_question_id' => $this->integer()->unsigned(),
19 | 'survey_user_answer_answer_id' => $this->bigInteger()->unsigned(),
20 | 'survey_user_answer_value' => $this->string(),
21 | 'survey_user_answer_text' => $this->text(),
22 | ], $tableOptions);
23 |
24 | $this->createIndex('fk_survey_user_answer_answer_idx', '{{%survey_user_answer}}', 'survey_user_answer_answer_id');
25 | $this->createIndex('fk_survey_user_answer_user_idx', '{{%survey_user_answer}}', 'survey_user_answer_user_id');
26 | $this->createIndex('idx_answer_value', '{{%survey_user_answer}}', ['survey_user_answer_answer_id', 'survey_user_answer_value']);
27 | $this->createIndex('idx_question_value', '{{%survey_user_answer}}', ['survey_user_answer_question_id', 'survey_user_answer_value']);
28 | $this->createIndex('ff_idx', '{{%survey_user_answer}}', 'survey_user_answer_survey_id');
29 | $this->createIndex('fk_survey_user_answer_question_idx', '{{%survey_user_answer}}', 'survey_user_answer_question_id');
30 | $this->createIndex('idx_survey_user_answer_value', '{{%survey_user_answer}}', 'survey_user_answer_value');
31 | }
32 |
33 | public function down()
34 | {
35 | $this->dropTable('{{%survey_user_answer}}');
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/migrations/m181018_070730_foreign_keys.php:
--------------------------------------------------------------------------------
1 | addForeignKey('fk_survey_answer_to_question', '{{%survey_answer}}', 'survey_answer_question_id', '{{%survey_question}}', 'survey_question_id', 'CASCADE', 'CASCADE');
11 | $this->addForeignKey('fk_survey_question_to_survey', '{{%survey_question}}', 'survey_question_survey_id', '{{%survey}}', 'survey_id', 'CASCADE', 'CASCADE');
12 | $this->addForeignKey('fk_survey_question_to_type', '{{%survey_question}}', 'survey_question_type', '{{%survey_type}}', 'survey_type_id', 'NO ACTION', 'CASCADE');
13 | $this->addForeignKey('fk_stat_to_survey', '{{%survey_stat}}', 'survey_stat_survey_id', '{{%survey}}', 'survey_id', 'CASCADE', 'CASCADE');
14 | $this->addForeignKey('fk_survey_user_answer_answer', '{{%survey_user_answer}}', 'survey_user_answer_answer_id', '{{%survey_answer}}', 'survey_answer_id', 'CASCADE', 'CASCADE');
15 | $this->addForeignKey('fk_survey_user_answer_question', '{{%survey_user_answer}}', 'survey_user_answer_question_id', '{{%survey_question}}', 'survey_question_id', 'CASCADE', 'CASCADE');
16 | $this->addForeignKey('fk_survey_user_answer_survey', '{{%survey_user_answer}}', 'survey_user_answer_survey_id', '{{%survey}}', 'survey_id', 'CASCADE', 'CASCADE');
17 |
18 | try {
19 | $this->addForeignKey('fk_survey_created_by', '{{%survey}}', 'survey_created_by', '{{%user}}', 'id', 'SET NULL', 'CASCADE');
20 | $this->addForeignKey('fk_stat_to_user', '{{%survey_stat}}', 'survey_stat_user_id', '{{%user}}', 'id', 'CASCADE', 'CASCADE');
21 | $this->addForeignKey('fk_survey_user_answer_user', '{{%survey_user_answer}}', 'survey_user_answer_user_id', '{{%user}}', 'id', 'SET NULL', 'SET NULL');
22 | } catch (\yii\db\Exception $e) {
23 | }
24 |
25 | }
26 |
27 | public function down()
28 | {
29 |
30 | $this->dropForeignKey('fk_survey_answer_to_question', '{{%survey_answer}}');
31 | $this->dropForeignKey('fk_survey_question_to_survey', '{{%survey_question}}');
32 | $this->dropForeignKey('fk_survey_question_to_type', '{{%survey_question}}');
33 | $this->dropForeignKey('fk_stat_to_survey', '{{%survey_stat}}');
34 | $this->dropForeignKey('fk_survey_user_answer_answer', '{{%survey_user_answer}}');
35 | $this->dropForeignKey('fk_survey_user_answer_question', '{{%survey_user_answer}}');
36 | $this->dropForeignKey('fk_survey_user_answer_survey', '{{%survey_user_answer}}');
37 |
38 | try {
39 | $this->dropForeignKey('fk_survey_created_by', '{{%survey}}');
40 | $this->dropForeignKey('fk_stat_to_user', '{{%survey_stat}}');
41 | $this->dropForeignKey('fk_survey_user_answer_user', '{{%survey_user_answer}}');
42 | } catch (\yii\db\Exception $e) {
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/migrations/m190918_224430_private_survey.php:
--------------------------------------------------------------------------------
1 | alterColumn('{{%survey}}', 'survey_updated_at', $this->timestamp()->null()->defaultValue(null));
10 | $this->alterColumn('{{%survey}}', 'survey_expired_at', $this->timestamp()->null()->defaultValue(null));
11 |
12 | $this->addColumn('{{%survey}}', 'survey_is_private', $this->boolean()->notNull()->defaultValue(false));
13 | $this->addColumn('{{%survey}}', 'survey_is_visible', $this->boolean()->notNull()->defaultValue(false));
14 |
15 | $this->createTable('{{%survey_restricted_user}}', [
16 | 'survey_restricted_user_id' => $this->primaryKey()->unsigned(),
17 | 'survey_restricted_user_survey_id' => $this->integer()->unsigned()->notNull(),
18 | 'survey_restricted_user_user_id' => $this->integer()->notNull(),
19 | ]);
20 |
21 | $this->addForeignKey('fk_survey_restricted_user_to_survey', '{{%survey_restricted_user}}', 'survey_restricted_user_survey_id', '{{%survey}}', 'survey_id', 'CASCADE', 'CASCADE');
22 |
23 | try {
24 | $this->addForeignKey('fk_survey_restricted_user_to_user', '{{%survey_restricted_user}}', 'survey_restricted_user_user_id', '{{%user}}', 'id', 'CASCADE', 'CASCADE');
25 | } catch (\yii\db\Exception $e) {
26 | }
27 | }
28 |
29 | public function down()
30 | {
31 | $this->dropForeignKey('fk_survey_restricted_user_to_survey', '{{%survey_restricted_user}}');
32 |
33 | try {
34 | $this->dropForeignKey('fk_survey_restricted_user_to_user', '{{%survey_restricted_user}}');
35 | } catch (\yii\db\Exception $e) {
36 | }
37 |
38 | $this->dropTable('{{%survey_restricted_user}}');
39 |
40 | $this->dropColumn('{{%survey}}', 'survey_is_private');
41 | $this->dropColumn('{{%survey}}', 'survey_is_visible');
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/models/Survey.php:
--------------------------------------------------------------------------------
1 | survey_created_by = \Yii::$app->user->getId();
61 | }
62 | return parent::beforeSave($insert);
63 | }
64 |
65 | /**
66 | * @inheritdoc
67 | */
68 | public function rules()
69 | {
70 | return [
71 | [['survey_created_at', 'survey_updated_at', 'survey_expired_at'], 'safe'],
72 | [['survey_is_pinned', 'survey_is_closed', 'survey_is_private', 'survey_is_visible'], 'boolean'],
73 | [['survey_name'], 'string', 'max' => 45],
74 | [['survey_descr'], 'string'],
75 | [['survey_tags', 'survey_image'], 'string', 'max' => 255],
76 | [['survey_name'], 'required'],
77 | [['survey_wallet', 'survey_status', 'survey_created_by', 'survey_time_to_pass', 'survey_badge_id'], 'integer'],
78 | [['imageFile'], 'file', 'mimeTypes' => 'image/jpeg, image/png', 'maxSize' => 5000000]
79 | ];
80 | }
81 |
82 | /**
83 | * @inheritdoc
84 | */
85 | public function attributeLabels()
86 | {
87 | return [
88 | 'survey_id' => Yii::t('survey', 'Survey ID'),
89 | 'survey_name' => Yii::t('survey', 'Name'),
90 | 'survey_created_at' => Yii::t('survey', 'Created at'),
91 | 'survey_updated_at' => Yii::t('survey', 'Updated at'),
92 | 'survey_expired_at' => Yii::t('survey', 'Expired at'),
93 | 'survey_is_pinned' => Yii::t('survey', 'Pinned'),
94 | 'survey_is_closed' => Yii::t('survey', 'Closed'),
95 | 'survey_is_private' => Yii::t('survey', 'Private'),
96 | 'survey_is_visible' => Yii::t('survey', 'Visible'),
97 | 'survey_wallet' => Yii::t('survey', 'Price'),
98 | 'survey_tags' => Yii::t('survey', 'Tags'),
99 | 'survey_descr' => Yii::t('survey', 'Description'),
100 | 'survey_time_to_pass' => Yii::t('survey', 'Time to pass'),
101 | 'restrictedUserIds' => Yii::t('survey', 'Restricted users'),
102 | 'imageFile' => '',
103 | ];
104 | }
105 |
106 | /**
107 | * @return \yii\db\ActiveQuery
108 | */
109 | public function getSurveyUserAnswers()
110 | {
111 | return $this->hasOne(SurveyUserAnswer::class, ['survey_user_answer_survey_id' => 'survey_id']);
112 | }
113 |
114 | /**
115 | * @return \yii\db\ActiveQuery
116 | */
117 | public function getQuestions()
118 | {
119 | return $this->hasMany(SurveyQuestion::class, ['survey_question_survey_id' => 'survey_id']);
120 | }
121 |
122 | /**
123 | * @return \yii\db\ActiveQuery
124 | */
125 | public function getStats()
126 | {
127 | return $this->hasMany(SurveyStat::class, ['survey_stat_survey_id' => 'survey_id']);
128 | }
129 |
130 | /**
131 | * @return \yii\db\ActiveQuery
132 | */
133 | public function getRestrictedUsers()
134 | {
135 | return $this->hasMany(Yii::$app->user->identityClass, ['id' => 'survey_restricted_user_user_id'])
136 | ->viaTable('survey_restricted_user', ['survey_restricted_user_survey_id' => 'survey_id']);
137 | }
138 |
139 | public function getStatus()
140 | {
141 | if (isset($this->survey_expired_at) && strtotime($this->survey_expired_at) < time()) {
142 | $status = 'expired';
143 | } else {
144 | $status = $this->survey_is_closed ? 'closed' : 'active';
145 | }
146 | return $status;
147 | }
148 |
149 | public function setQuestions($val)
150 | {
151 | return $this->questions = $val;
152 | }
153 |
154 | public function getRespondentsCount()
155 | {
156 | return SurveyStat::find()->where(['survey_stat_survey_id' => $this->survey_id])->count();
157 | }
158 |
159 | public function getCompletedRespondentsCount()
160 | {
161 | return SurveyStat::find()->where(['survey_stat_survey_id' => $this->survey_id])
162 | ->andWhere(['survey_stat_is_done' => true])
163 | ->count();
164 | }
165 |
166 | static function getDropdownList()
167 | {
168 | return ArrayHelper::map(self::find()
169 | ->leftJoin('survey_restricted_user', 'survey_id = survey_restricted_user_survey_id')
170 | ->where(new AndCondition([
171 | ['survey_is_visible' => 1],
172 | new OrCondition([
173 | ['>', 'survey_expired_at', new Expression('NOW()')],
174 | ['survey_expired_at' => null]
175 | ]),
176 | new OrCondition([
177 | ['survey_is_private' => 0],
178 | ['survey_restricted_user_user_id' => \Yii::$app->user->id]
179 | ])
180 | ]))
181 | ->orderBy(['survey_created_at' => SORT_ASC])
182 | ->asArray()->all(), 'survey_id', 'survey_name');
183 | }
184 |
185 | /**
186 | * @return string
187 | */
188 | public function getImage()
189 | {
190 | $file = !empty($this->survey_image) ? $this->survey_image : null;
191 |
192 | if (empty($file)) {
193 | return null;
194 | }
195 | $module = \Yii::$app->getModule('survey');
196 | $basepath = $module->params['uploadsUrl'];
197 | $path = $basepath . '/' . $this->survey_image;
198 |
199 | return $path;
200 | }
201 |
202 | public function getAuthorName()
203 | {
204 | try {
205 | $userClass = \Yii::$app->user->identityClass;
206 | $author = $userClass::findOne($this->survey_created_by);
207 | if ($author) {
208 | return $author->username;
209 | } else {
210 | return null;
211 | }
212 | } catch (\Throwable $e) {
213 | return 'undefined';
214 | }
215 | }
216 |
217 | public static function assignRestrictedUser($userId, $surveyId) {
218 | $survey = self::findOne($surveyId);
219 | $userClass = \Yii::$app->user->identityClass;
220 | $survey->link('restrictedUsers', $userClass::findOne($userId));
221 | return true;
222 | }
223 |
224 | public static function unassignRestrictedUser($userId, $surveyId) {
225 | $survey = self::findOne($surveyId);
226 | $userClass = \Yii::$app->user->identityClass;
227 | $survey->unlink('restrictedUsers', $userClass::findOne($userId), true);
228 | return true;
229 | }
230 |
231 | public function getRestrictedUsersCount()
232 | {
233 | return self::find()
234 | ->innerJoin('survey_restricted_user', 'survey_id = survey_restricted_user_survey_id')
235 | ->where(['survey_id' => $this->survey_id])
236 | ->count();
237 | }
238 |
239 | public function getRestrictedUserIds() {
240 | return ArrayHelper::map($this->restrictedUsers, 'id', 'id');
241 | }
242 |
243 | public function getRestrictedUserNames() {
244 | return ArrayHelper::map($this->restrictedUsers, 'id', 'fullname');
245 | }
246 |
247 | public function isAccessibleBy($userId) {
248 | return ($this->survey_is_visible && (!$this->survey_is_private || in_array($userId, $this->restrictedUserIds)));
249 | }
250 |
251 | public function getIsAccessibleByCurrentUser() {
252 | return $this->isAccessibleBy(\Yii::$app->user->id);
253 | }
254 | }
255 |
--------------------------------------------------------------------------------
/models/SurveyAnswer.php:
--------------------------------------------------------------------------------
1 | 'intval'],
44 | [['survey_answer_show_descr'], 'boolean'],
45 | [['survey_answer_show_descr'], 'filter', 'filter' => 'boolval'],
46 | [['survey_answer_name'], 'string', 'max' => 100],
47 | [['survey_answer_name'], 'required'],
48 | [['survey_answer_class', 'survey_answer_comment'], 'string', 'max' => 255],
49 | [['survey_answer_question_id'], 'exist', 'skipOnError' => true, 'targetClass' => SurveyQuestion::class, 'targetAttribute' => ['survey_answer_question_id' => 'survey_question_id']],
50 | ];
51 | }
52 |
53 |
54 |
55 | public function afterDelete()
56 | {
57 | $question = $this->question;
58 | if (!empty($question)) {
59 | $answersCount = $question->getAnswers()->count();
60 | if ($answersCount == 0) {
61 | //prevent deleting last answer
62 | $question->link('answers', (new SurveyAnswer(['survey_answer_sort' => 0])));
63 | }
64 | }
65 |
66 | return parent::afterDelete();
67 | }
68 |
69 | /**
70 | * @inheritdoc
71 | */
72 | public function attributeLabels()
73 | {
74 | return [
75 | 'survey_answer_id' => Yii::t('survey', 'Answer ID'),
76 | 'survey_answer_name' => Yii::t('survey', 'Answer'),
77 | 'survey_answer_descr' => Yii::t('survey', 'Detailed description'),
78 | 'survey_answer_show_descr' => Yii::t('survey', 'Show detailed description'),
79 | 'survey_answer_class' => Yii::t('survey', 'Class'),
80 | 'survey_answer_comment' => Yii::t('survey', 'Comment'),
81 | 'survey_answer_question_id' => Yii::t('survey', 'Question ID'),
82 | 'survey_answer_points' => Yii::t('survey', 'Points'),
83 | ];
84 | }
85 |
86 | /**
87 | * @return \yii\db\ActiveQuery
88 | */
89 | public function getQuestion()
90 | {
91 | return $this->hasOne(SurveyQuestion::class, ['survey_question_id' => 'survey_answer_question_id']);
92 | }
93 |
94 | /**
95 | * @return \yii\db\ActiveQuery
96 | */
97 | public function getUserAnswers()
98 | {
99 | return $this->hasMany(SurveyUserAnswer::class, ['survey_user_answer_answer_id' => 'survey_answer_id']);
100 | }
101 |
102 | /**
103 | * Returns the total number of users voted for this answer
104 | *
105 | * @return int
106 | */
107 | public function getTotalUserAnswersCount()
108 | {
109 | switch ($this->question->survey_question_type){
110 | case SurveyType::TYPE_MULTIPLE:
111 | $result = SurveyUserAnswer::find()->where(['survey_user_answer_answer_id' => $this->survey_answer_id])
112 | ->andWhere(['survey_user_answer_value' => 1])
113 | ->count();
114 | break;
115 | case SurveyType::TYPE_ONE_OF_LIST:
116 | case SurveyType::TYPE_DROPDOWN:
117 | $result = SurveyUserAnswer::find()->andWhere(['survey_user_answer_value' => $this->survey_answer_id])
118 | ->count();
119 | break;
120 | case SurveyType::TYPE_RANKING:
121 |
122 | $result = (new Query())
123 | ->from(SurveyUserAnswer::tableName())
124 | ->addSelect(['AVG(survey_user_answer_value) average'])
125 | ->where(['survey_user_answer_answer_id' => $this->survey_answer_id])
126 | ->andWhere(['>', 'survey_user_answer_value', 0])
127 | ->groupBy(['survey_user_answer_answer_id'])->scalar();
128 | break;
129 | case SurveyType::TYPE_SLIDER:
130 | $result = (new Query())
131 | ->from(SurveyUserAnswer::tableName())
132 | ->addSelect(['AVG(survey_user_answer_value) average'])
133 | ->andWhere(['survey_user_answer_question_id' => $this->question->survey_question_id])
134 | ->andWhere(['is not', 'survey_user_answer_value', null])
135 | ->groupBy(['survey_user_answer_question_id'])->scalar();
136 | break;
137 | default:
138 | $result = 0;
139 | break;
140 | }
141 |
142 | return $result;
143 |
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/models/SurveyQuestion.php:
--------------------------------------------------------------------------------
1 | userAnswers;
42 | if (!$question->survey_question_can_skip){
43 | if ($question->survey_question_type === SurveyType::TYPE_MULTIPLE){
44 | $answerValues = ArrayHelper::getColumn($userAnswers, 'survey_user_answer_value');
45 | if (!in_array("1", $answerValues)){
46 | $answer = (array)$question->userAnswers;
47 | if(!empty($answer)) {
48 | end($answer)->addError('survey_user_answer_value', \Yii::t('survey', 'You must enter an answer'));
49 | }
50 | }
51 | }
52 | }
53 | return true;
54 | }
55 |
56 | public function changeDefaultValuesOnTypeChange(){
57 | /** @var SurveyQuestion $question */
58 | $question = $this;
59 | $oldType = $question->getOldAttribute('survey_question_type');
60 | $newType = $question->getAttribute('survey_question_type');
61 | if ($oldType === $newType){
62 | return true;
63 | }
64 |
65 | if ($newType === SurveyType::TYPE_SLIDER){
66 | $question->unlinkAll('answers', true);
67 | for ($i = 1; $i <= 2; ++$i) {
68 | $answer = new SurveyAnswer();
69 | $answer->survey_answer_sort = $i;
70 | $answer->survey_answer_name = ($i === 1) ? 0 : 100;
71 | $question->link('answers', $answer);
72 | }
73 | }else if($oldType === SurveyType::TYPE_SLIDER){
74 | $question->unlinkAll('answers', true);
75 | for ($i = 1; $i <= 2; ++$i) {
76 | $answer = new SurveyAnswer();
77 | $answer->survey_answer_sort = $i;
78 | $question->link('answers', $answer);
79 | }
80 | }
81 |
82 | return true;
83 | }
84 |
85 | /**
86 | * @inheritdoc
87 | */
88 | public function rules()
89 | {
90 | return [
91 | [['survey_question_descr'], 'string'],
92 | [['survey_question_type', 'survey_question_survey_id'], 'integer'],
93 | [['survey_question_type'], 'filter', 'filter' => 'intval'],
94 | [['survey_question_can_skip', 'survey_question_show_descr', 'survey_question_is_scorable'], 'boolean'],
95 | [['survey_question_can_skip', 'survey_question_show_descr', 'survey_question_is_scorable'], 'filter', 'filter' => 'boolval'],
96 | [['survey_question_name'], 'string', 'max' => 130],
97 | [['survey_question_name'], 'required'],
98 | [['survey_question_survey_id'], 'exist', 'skipOnError' => true, 'targetClass' => Survey::class, 'targetAttribute' => ['survey_question_survey_id' => 'survey_id']],
99 | [['survey_question_type'], 'exist', 'skipOnError' => true, 'targetClass' => SurveyType::class, 'targetAttribute' => ['survey_question_type' => 'survey_type_id']],
100 | ];
101 | }
102 |
103 | public function beforeSave($insert)
104 | {
105 | //scorable questions
106 | if (!$insert && !in_array($this->survey_question_type, [
107 | SurveyType::TYPE_MULTIPLE,
108 | SurveyType::TYPE_ONE_OF_LIST,
109 | SurveyType::TYPE_DROPDOWN
110 | ])) {
111 | if ($this->survey_question_is_scorable){
112 | $this->survey_question_is_scorable = false;
113 | }
114 | }
115 | return parent::beforeSave($insert); // TODO: Change the autogenerated stub
116 | }
117 |
118 | public function loadDefaultValues($skipIfSet = true)
119 | {
120 | parent::loadDefaultValues($skipIfSet);
121 | $this->survey_question_type = SurveyType::TYPE_MULTIPLE; //multiple choice
122 | return $this;
123 | }
124 |
125 | /**
126 | * @inheritdoc
127 | */
128 | public function attributeLabels()
129 | {
130 | return [
131 | 'survey_question_id' => Yii::t('survey', 'Question ID'),
132 | 'survey_question_name' => Yii::t('survey', 'Survey Question Name'),
133 | 'survey_question_descr' => Yii::t('survey', 'Detailed description'),
134 | 'survey_question_type' => Yii::t('survey', 'Question Type'),
135 | 'survey_question_survey_id' => Yii::t('survey', 'Survey ID'),
136 | 'survey_question_can_skip' => Yii::t('survey', 'Can be skipped'),
137 | 'survey_question_show_descr' => Yii::t('survey', 'Show detailed description'),
138 | 'survey_question_is_scorable' => Yii::t('survey', 'Score this question'),
139 | ];
140 | }
141 |
142 | /**
143 | * @return \yii\db\ActiveQuery
144 | */
145 | public function getAnswers()
146 | {
147 | return $this->hasMany(SurveyAnswer::class, ['survey_answer_question_id' => 'survey_question_id'])
148 | ->orderBy(['survey_answer_sort' => SORT_ASC, 'survey_answer_id' => SORT_ASC]);
149 | }
150 |
151 | /**
152 | * @return \yii\db\ActiveQuery
153 | */
154 | public function getSurvey()
155 | {
156 | return $this->hasOne(Survey::class, ['survey_id' => 'survey_question_survey_id']);
157 | }
158 |
159 | /**
160 | * @return \yii\db\ActiveQuery
161 | */
162 | public function getQuestionType()
163 | {
164 | return $this->hasOne(SurveyType::class, ['survey_type_id' => 'survey_question_type']);
165 | }
166 |
167 | /**
168 | * @return \yii\db\ActiveQuery
169 | */
170 | public function getUserAnswers()
171 | {
172 | return $this->hasMany(SurveyUserAnswer::class, ['survey_user_answer_question_id' => 'survey_question_id'])
173 | ->andOnCondition(['survey_user_answer_user_id' => \Yii::$app->user->getId()])
174 | ->indexBy('survey_user_answer_answer_id');
175 | }
176 |
177 | /**
178 | * Returns the total number of users voted for this answer
179 | *
180 | * @return int
181 | */
182 | public function getTotalUserAnswersCount()
183 | {
184 | switch ($this->survey_question_type){
185 | case SurveyType::TYPE_MULTIPLE:
186 | $result = SurveyUserAnswer::find()->where(['survey_user_answer_question_id' => $this->survey_question_id])
187 | ->andWhere(['survey_user_answer_value' => 1])
188 | ->count();
189 | break;
190 | case SurveyType::TYPE_ONE_OF_LIST:
191 | case SurveyType::TYPE_DROPDOWN:
192 | $result = SurveyUserAnswer::find()->where(['survey_user_answer_question_id' => $this->survey_question_id])
193 | ->andWhere(['>', 'survey_user_answer_value', 0])
194 | ->count();
195 | break;
196 | default:
197 | $result = 0;
198 | break;
199 | }
200 |
201 | return $result;
202 | }
203 | }
204 |
--------------------------------------------------------------------------------
/models/SurveyStat.php:
--------------------------------------------------------------------------------
1 | survey_stat_hash = self::generateHash($this->survey_stat_survey_id, $this->survey_stat_user_id);
47 | }
48 | return parent::beforeSave($insert);
49 | }
50 |
51 | public function afterSave($insert, $changedAttributes)
52 | {
53 | parent::afterSave($insert, $changedAttributes);
54 | if ($insert){
55 | \Yii::$app->trigger(self::EVENT_SURVEY_HAS_BEEN_ASSIGN, new Event(['sender' => $this]));
56 | }
57 |
58 | if (isset($changedAttributes['survey_stat_is_done']) && $changedAttributes['survey_stat_is_done'] === false){
59 | Event::trigger(self::class, self::EVENT_SURVEY_AFTER_COMPLETE, new Event(['sender' => $this]));
60 | \Yii::$app->trigger(self::EVENT_SURVEY_AFTER_COMPLETE, new Event(['sender' => $this]));
61 | }
62 | }
63 |
64 | /**
65 | * @param $survey_stat_survey_id
66 | * @param $survey_stat_user_id
67 | * @return string
68 | */
69 | static function generateHash($survey_stat_survey_id, $survey_stat_user_id){
70 | return md5($survey_stat_survey_id . $survey_stat_user_id);
71 | }
72 |
73 | public function behaviors()
74 | {
75 | return [
76 | [
77 | 'class' => TimestampBehavior::class,
78 | 'attributes' => [
79 | BaseActiveRecord::EVENT_BEFORE_INSERT => ['survey_stat_assigned_at'],
80 | BaseActiveRecord::EVENT_BEFORE_UPDATE => ['survey_stat_updated_at'],
81 | ],
82 | 'createdAtAttribute' => 'survey_stat_assigned_at',
83 | 'updatedAtAttribute' => 'survey_stat_updated_at',
84 | 'skipUpdateOnClean' => true,
85 | 'value' => new Expression('NOW()'),
86 | ],
87 | ];
88 | }
89 |
90 | /**
91 | * @inheritdoc
92 | */
93 | public function rules()
94 | {
95 | return [
96 | [['survey_stat_survey_id', 'survey_stat_user_id', 'survey_stat_hash'], 'required'],
97 | [['survey_stat_survey_id', 'survey_stat_user_id'], 'integer'],
98 | [['survey_stat_assigned_at', 'survey_stat_started_at', 'survey_stat_updated_at', 'survey_stat_ended_at'], 'safe'],
99 | [['survey_stat_is_done'], 'boolean'],
100 | [['survey_stat_ip'], 'string', 'max' => 45],
101 | [['survey_stat_hash'], 'string', 'max' => 32],
102 | [['survey_stat_survey_id'], 'exist', 'skipOnError' => true, 'targetClass' => Survey::class, 'targetAttribute' => ['survey_stat_survey_id' => 'survey_id']],
103 | [['survey_stat_user_id'], 'exist', 'skipOnError' => true, 'targetClass' => \Yii::$app->user->identityClass, 'targetAttribute' => ['survey_stat_user_id' => 'id']],
104 | ];
105 | }
106 |
107 | /**
108 | * @inheritdoc
109 | */
110 | public function attributeLabels()
111 | {
112 | return [
113 | 'survey_stat_id' => Yii::t('survey', 'Survey Stat ID'),
114 | 'survey_stat_survey_id' => Yii::t('survey', 'Survey Stat Survey ID'),
115 | 'survey_stat_user_id' => Yii::t('survey', 'Survey Stat User ID'),
116 | 'survey_stat_assigned_at' => Yii::t('survey', 'Survey Stat Assigned At'),
117 | 'survey_stat_started_at' => Yii::t('survey', 'Survey Stat Started At'),
118 | 'survey_stat_updated_at' => Yii::t('survey', 'Survey Stat Updated At'),
119 | 'survey_stat_ended_at' => Yii::t('survey', 'Survey Stat Ended At'),
120 | 'survey_stat_ip' => Yii::t('survey', 'Survey Stat Ip'),
121 | 'survey_stat_is_done' => Yii::t('survey', 'Survey Stat Is Done'),
122 | ];
123 | }
124 |
125 | /**
126 | * @return \yii\db\ActiveQuery
127 | */
128 | public function getSurvey()
129 | {
130 | return $this->hasOne(Survey::class, ['survey_id' => 'survey_stat_survey_id']);
131 | }
132 |
133 | /**
134 | * @return \yii\db\ActiveQuery
135 | */
136 | public function getUser()
137 | {
138 | $userClass = \Yii::$app->user->identityClass;
139 | return $this->hasOne($userClass, ['id' => 'survey_stat_user_id']);
140 | }
141 |
142 | /**
143 | * @param $userId
144 | * @param $surveyId
145 | * @return bool
146 | * @throws UserException
147 | */
148 | static function assignUser($userId, $surveyId){
149 |
150 | $user = Survey::findOne($surveyId);
151 | if (!$user) {
152 | throw new UserException('survey does not exist');
153 | }
154 |
155 | /** @var \app\modules\user\models\User $User */
156 | $User = \Yii::$app->user->identityClass;
157 | $user = $User::findOne($userId);
158 | if (!$user) {
159 | throw new UserException('user does not exist');
160 | }
161 |
162 | $isAssigned = SurveyStat::find()->where(['survey_stat_survey_id' => $surveyId])
163 | ->andWhere(['survey_stat_user_id' => $userId])->count();
164 | if ($isAssigned){
165 | throw new UserException('user already assigned', 1001);
166 | }
167 |
168 | $surveyStat = new SurveyStat();
169 | $surveyStat->survey_stat_user_id = $userId;
170 | $surveyStat->survey_stat_survey_id = $surveyId;
171 | if ($surveyStat->save(false)){
172 |
173 | return true;
174 | }else {
175 | return false;
176 | }
177 | }
178 |
179 | static function unassignUser($userId, $surveyId){
180 |
181 | $user = Survey::findOne($surveyId);
182 | if (!$user) {
183 | throw new UserException('survey does not exist');
184 | }
185 |
186 | /** @var \app\modules\user\models\User $User */
187 | $User = \Yii::$app->user->identityClass;
188 | $user = $User::findOne($userId);
189 | if (!$user) {
190 | throw new UserException('user does not exist');
191 | }
192 |
193 | return SurveyStat::deleteAll(['survey_stat_survey_id' => $surveyId, 'survey_stat_user_id' => $userId]);
194 | }
195 |
196 | /**
197 | * @param $userId
198 | * @param $surveyId
199 | * @return array|null|SurveyStat
200 | * @throws UserException
201 | */
202 | static function getAssignedUserStat($userId, $surveyId){
203 |
204 | $user = Survey::findOne($surveyId);
205 | if (!$user) {
206 | throw new UserException('survey does not exist');
207 | }
208 |
209 | /** @var \app\modules\user\models\User $User */
210 | $User = \Yii::$app->user->identityClass;
211 | $user = $User::findOne($userId);
212 | if (!$user) {
213 | throw new UserException('user does not exist');
214 | }
215 |
216 | $result = SurveyStat::find()->where(['survey_stat_survey_id' => $surveyId])
217 | ->andWhere(['survey_stat_user_id' => $userId])->one();
218 |
219 | return $result;
220 | }
221 | }
222 |
--------------------------------------------------------------------------------
/models/SurveyType.php:
--------------------------------------------------------------------------------
1 | 45],
45 | [['survey_type_descr'], 'string', 'max' => 255],
46 | ];
47 | }
48 |
49 | /**
50 | * @inheritdoc
51 | */
52 | public function attributeLabels()
53 | {
54 | return [
55 | 'survey_type_id' => Yii::t('survey', 'Survey Type ID'),
56 | 'survey_type_name' => Yii::t('survey', 'Type'),
57 | 'survey_type_descr' => Yii::t('survey', 'Description'),
58 | ];
59 | }
60 |
61 | public static function getDropdownList()
62 | {
63 | return ArrayHelper::map(SurveyType::find()
64 | ->asArray()->all(), 'survey_type_id', function($model){
65 | return \Yii::t('survey', $model['survey_type_name']);
66 | });
67 | }
68 |
69 | /**
70 | * @return \yii\db\ActiveQuery
71 | */
72 | public function getSurveyQuestions()
73 | {
74 | return $this->hasMany(SurveyQuestion::class, ['survey_question_type' => 'survey_type_id']);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/models/SurveyUserAnswer.php:
--------------------------------------------------------------------------------
1 | 255],
42 | [['survey_user_answer_text'], 'string'],
43 |
44 | [['survey_user_answer_value'], 'required', 'when' => function($model){
45 | /** @var $model SurveyUserAnswer */
46 | return ($model->question->survey_question_can_skip == false && $model->question->survey_question_type !== SurveyType::TYPE_COMMENT_BOX);
47 | }, 'message' => \Yii::t('survey', 'You must enter an answer')],
48 |
49 | [['survey_user_answer_text'], 'required', 'when' => function($model){
50 | /** @var $model SurveyUserAnswer */
51 | return ($model->question->survey_question_can_skip == false && $model->question->survey_question_type === SurveyType::TYPE_COMMENT_BOX);
52 | }, 'message' => \Yii::t('survey', 'You must enter an answer')],
53 |
54 | [['survey_user_answer_value', 'survey_user_answer_text'], function ($attribute, $params, $validator) {
55 | /** @var $this SurveyUserAnswer */
56 | if (!$this->question->survey->isAccessibleByCurrentUser) {
57 | $this->addError($attribute, \Yii::t('survey', 'You are not allowed to answer this survey'));
58 | }
59 | }],
60 |
61 | [['survey_user_answer_value', 'survey_user_answer_text'], 'default', 'value' => null],
62 | [['survey_user_answer_answer_id'], 'exist', 'skipOnError' => true, 'targetClass' => SurveyAnswer::class, 'targetAttribute' => ['survey_user_answer_answer_id' => 'survey_answer_id']],
63 | [['survey_user_answer_question_id'], 'exist', 'skipOnError' => true, 'targetClass' => SurveyQuestion::class, 'targetAttribute' => ['survey_user_answer_question_id' => 'survey_question_id']],
64 | [['survey_user_answer_survey_id'], 'exist', 'skipOnError' => true, 'targetClass' => Survey::class, 'targetAttribute' => ['survey_user_answer_survey_id' => 'survey_id']],
65 | [['survey_user_answer_user_id'], 'exist', 'skipOnError' => true, 'targetClass' => \Yii::$app->user->identityClass::className(), 'targetAttribute' => ['survey_user_answer_user_id' => 'id']],
66 | ];
67 | }
68 |
69 | public function beforeValidate()
70 | {
71 | $stat = SurveyStat::getAssignedUserStat(\Yii::$app->user->getId(), $this->question->survey_question_survey_id);
72 | if ($stat && $stat->survey_stat_is_done){
73 | return false;
74 | }
75 |
76 | return parent::beforeValidate();
77 | }
78 |
79 | /**
80 | * @inheritdoc
81 | */
82 | public function attributeLabels()
83 | {
84 | return [
85 | 'survey_user_answer_id' => Yii::t('survey', 'Survey User Answer ID'),
86 | 'survey_user_answer_user_id' => Yii::t('survey', 'Survey User Answer User ID'),
87 | 'survey_user_answer_survey_id' => Yii::t('survey', 'Survey User Answer Survey ID'),
88 | 'survey_user_answer_question_id' => Yii::t('survey', 'Survey User Answer Question ID'),
89 | 'survey_user_answer_answer_id' => Yii::t('survey', 'Survey User Answer Answer ID'),
90 | 'survey_user_answer_value' => Yii::t('survey', 'Answer'),
91 | ];
92 | }
93 |
94 | /**
95 | * @return \yii\db\ActiveQuery
96 | */
97 | public function getSurveyUserAnswerAnswer()
98 | {
99 | return $this->hasOne(SurveyAnswer::class, ['survey_answer_id' => 'survey_user_answer_answer_id']);
100 | }
101 |
102 | /**
103 | * @return \yii\db\ActiveQuery
104 | */
105 | public function getQuestion()
106 | {
107 | return $this->hasOne(SurveyQuestion::class, ['survey_question_id' => 'survey_user_answer_question_id']);
108 | }
109 |
110 | /**
111 | * @return \yii\db\ActiveQuery
112 | */
113 | public function getSurveyUserAnswerSurvey()
114 | {
115 | return $this->hasOne(Survey::class, ['survey_id' => 'survey_user_answer_survey_id']);
116 | }
117 |
118 | /**
119 | * @return \yii\db\ActiveQuery
120 | */
121 | public function getUser()
122 | {
123 | return $this->hasOne(\Yii::$app->user->identityClass::className(), ['id' => 'survey_user_answer_user_id']);
124 | }
125 |
126 |
127 | }
128 |
--------------------------------------------------------------------------------
/models/search/SurveySearch.php:
--------------------------------------------------------------------------------
1 | $query,
49 | 'pagination' => ['defaultPageSize' => 10],
50 | 'sort' => ['defaultOrder' => ['survey_created_at' => SORT_DESC]]
51 | ]);
52 |
53 | $this->load($params);
54 |
55 | if (!$this->validate()) {
56 | // uncomment the following line if you do not want to return any records when validation fails
57 | $query->where('0=1');
58 | return $dataProvider;
59 | }
60 |
61 | $query->andFilterWhere([
62 | 'survey_id' => $this->survey_id,
63 | 'survey_created_at' => $this->survey_created_at,
64 | 'survey_updated_at' => $this->survey_updated_at,
65 | 'survey_expired_at' => $this->survey_expired_at,
66 | 'survey_is_pinned' => $this->survey_is_pinned,
67 | 'survey_is_closed' => $this->survey_is_closed,
68 | ]);
69 |
70 | $query->andFilterWhere(['like', 'survey_name', $this->survey_name]);
71 |
72 | return $dataProvider;
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/models/search/SurveyStatSearch.php:
--------------------------------------------------------------------------------
1 | $query->joinWith('survey'),
49 | 'sort' => ['defaultOrder' => ['survey_stat_assigned_at' => SORT_DESC]]
50 |
51 | ]);
52 |
53 | $this->load($params);
54 |
55 | if (!$this->validate()) {
56 | // uncomment the following line if you do not want to return any records when validation fails
57 | $query->where('0=1');
58 | return $dataProvider;
59 | }
60 |
61 | $query->andFilterWhere([
62 | 'survey_stat_id' => $this->survey_stat_id,
63 | 'survey_stat_survey_id' => $this->survey_stat_survey_id,
64 | 'survey_stat_user_id' => $this->survey_stat_user_id,
65 | 'survey_stat_assigned_at' => $this->survey_stat_assigned_at,
66 | 'survey_stat_started_at' => $this->survey_stat_started_at,
67 | 'survey_stat_updated_at' => $this->survey_stat_updated_at,
68 | 'survey_stat_ended_at' => $this->survey_stat_ended_at,
69 | 'survey_stat_is_done' => $this->survey_stat_is_done,
70 | ]);
71 |
72 | $query->andFilterWhere(['like', 'survey_stat_ip', $this->survey_stat_ip]);
73 |
74 | return $dataProvider;
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/views/answers/1.php:
--------------------------------------------------------------------------------
1 | answers as $i => $answer) {
17 | echo Html::checkbox('checkbox', false, ['class' => 'pseudo-checkbox']);
18 | echo $form->field($answer, "[$question->survey_question_id][$i]survey_answer_name")->input('text',
19 | ['placeholder' => \Yii::t('survey', 'Enter an answer choice')])->label(false);
20 |
21 | if ($question->survey_question_is_scorable) {
22 | echo Html::beginTag('div', ['class' => 'points-wrap']);
23 | if ($i === 0) {
24 | echo Html::tag('span', 'Баллы', ['class' => 'points-title']);
25 | }
26 | echo $form->field($answer, "[$question->survey_question_id][$i]survey_answer_points")->input('number')->label(false);
27 | echo Html::endTag('div');
28 | }
29 |
30 | echo Html::submitButton('', ['class' => 'btn btn-success btn-add-answer survey-question-submit',
31 | 'data-action' => Url::toRoute(['question/add-answer', 'id' => $question->survey_question_id, 'after' => $i])]);
32 | echo Html::submitButton('', ['class' => 'btn btn-danger btn-delete-answer survey-question-submit',
33 | 'data-action' => Url::toRoute(['question/delete-answer', 'id' => $question->survey_question_id, 'answer' => $i]),
34 | 'name' => 'action', 'value' => 'delete-answer'
35 | ]);
36 |
37 | echo $form->field($answer, "[{$question->survey_question_id}][$i]survey_answer_show_descr",
38 | ['options' => [
39 | 'class' => 'form-group checkbox-inline'
40 | ]])->checkbox(['class' => 'checkbox-updatable']);
41 | echo Html::tag('br', '');
42 |
43 | if ($answer->survey_answer_show_descr) {
44 | echo $form->field($answer, "[{$question->survey_question_id}][$i]survey_answer_descr")->widget(Widget::class, [
45 | 'settings' => [
46 | 'lang' => 'ru',
47 | 'minHeight' => 100,
48 | 'toolbarFixed' => false,
49 | 'imageManagerJson' => Url::toRoute(['question/images-get']),
50 | 'imageUpload' => Url::toRoute(['question/image-upload']),
51 | 'fileManagerJson' => Url::toRoute(['question/files-get']),
52 | 'fileUpload' => Url::toRoute(['question/file-upload']),
53 | 'plugins' => [
54 | 'imagemanager',
55 | 'video',
56 | 'fullscreen',
57 | 'filemanager',
58 | 'fontsize',
59 | 'fontcolor',
60 | 'table',
61 | ]
62 | ]
63 | ])->label(false);
64 | }
65 |
66 | echo Html::tag('br', '');
67 | }
--------------------------------------------------------------------------------
/views/answers/10.php:
--------------------------------------------------------------------------------
1 | field()
10 | foreach ($question->answers as $i => $answer) {
11 |
12 | echo $form->field($answer, "[$question->survey_question_id][$i]survey_answer_name")->input('text',
13 | ['placeholder' => \Yii::t('survey', 'Enter an answer choice')])->label(false);
14 |
15 | if ($question->survey_question_is_scorable) {
16 | echo Html::beginTag('div', ['class' => 'points-wrap']);
17 | if ($i === 0) {
18 | echo Html::tag('span', 'Баллы', ['class' => 'points-title']);
19 | }
20 | echo $form->field($answer, "[$question->survey_question_id][$i]survey_answer_points")->input('number')->label(false);
21 | echo Html::endTag('div');
22 | }
23 |
24 | echo Html::submitButton(\Yii::t('survey', ''), ['class' => 'btn btn-success btn-add-answer survey-question-submit',
25 | 'data-action' => Url::toRoute(['question/add-answer', 'id' => $question->survey_question_id, 'after' => $i])]);
26 | echo Html::submitButton(\Yii::t('survey', ''), ['class' => 'btn btn-danger btn-delete-answer survey-question-submit',
27 | 'data-action' => Url::toRoute(['question/delete-answer', 'id' => $question->survey_question_id, 'answer' => $i]),
28 | 'name' => 'action', 'value' => 'delete-answer'
29 | ]);
30 |
31 | echo Html::tag('br', '');
32 | }
--------------------------------------------------------------------------------
/views/answers/2.php:
--------------------------------------------------------------------------------
1 | field()
17 | foreach ($question->answers as $i => $answer) {
18 | echo Html::radio('radio', false, ['class' => 'pseudo-checkbox']);
19 | echo $form->field($answer, "[$question->survey_question_id][$i]survey_answer_name")->input('text',
20 | ['placeholder' => \Yii::t('survey', 'Enter an answer choice')])->label(false);
21 |
22 | if ($question->survey_question_is_scorable) {
23 | echo Html::beginTag('div', ['class' => 'points-wrap']);
24 | if ($i === 0) {
25 | echo Html::tag('span', 'Баллы', ['class' => 'points-title']);
26 | }
27 | echo $form->field($answer, "[$question->survey_question_id][$i]survey_answer_points")->input('number')->label(false);
28 | echo Html::endTag('div');
29 | }
30 |
31 | echo Html::submitButton(\Yii::t('survey', ''), ['class' => 'btn btn-success btn-add-answer survey-question-submit',
32 | 'data-action' => Url::toRoute(['question/add-answer', 'id' => $question->survey_question_id, 'after' => $i])]);
33 | echo Html::submitButton(\Yii::t('survey', ''), ['class' => 'btn btn-danger btn-delete-answer survey-question-submit',
34 | 'data-action' => Url::toRoute(['question/delete-answer', 'id' => $question->survey_question_id, 'answer' => $i]),
35 | 'name' => 'action', 'value' => 'delete-answer'
36 | ]);
37 |
38 | echo $form->field($answer, "[{$question->survey_question_id}][$i]survey_answer_show_descr",
39 | ['options' => [
40 | 'class' => 'form-group checkbox-inline'
41 | ]])->checkbox(['class' => 'checkbox-updatable']);
42 | echo Html::tag('br', '');
43 |
44 | if ($answer->survey_answer_show_descr) {
45 | echo $form->field($answer, "[{$question->survey_question_id}][$i]survey_answer_descr")->widget(Widget::class, [
46 | 'settings' => [
47 | 'lang' => 'ru',
48 | 'minHeight' => 100,
49 | 'toolbarFixed' => false,
50 | 'imageManagerJson' => Url::toRoute(['question/images-get']),
51 | 'imageUpload' => Url::toRoute(['question/image-upload']),
52 | 'fileManagerJson' => Url::toRoute(['question/files-get']),
53 | 'fileUpload' => Url::toRoute(['question/file-upload']),
54 | 'plugins' => [
55 | 'imagemanager',
56 | 'video',
57 | 'fullscreen',
58 | 'filemanager',
59 | 'fontsize',
60 | 'fontcolor',
61 | 'table',
62 | ]
63 | ]
64 | ])->label(false);
65 | }
66 |
67 | echo Html::tag('br', '');
68 | }
--------------------------------------------------------------------------------
/views/answers/3.php:
--------------------------------------------------------------------------------
1 | field()
16 | foreach ($question->answers as $i => $answer) {
17 |
18 | echo $form->field($answer, "[$question->survey_question_id][$i]survey_answer_name")->input('text',
19 | ['placeholder' => \Yii::t('survey', 'Enter an answer choice')])->label(false);
20 |
21 | if ($question->survey_question_is_scorable) {
22 | echo Html::beginTag('div', ['class' => 'points-wrap']);
23 | if ($i === 0) {
24 | echo Html::tag('span', 'Баллы', ['class' => 'points-title']);
25 | }
26 | echo $form->field($answer, "[$question->survey_question_id][$i]survey_answer_points")->input('number')->label(false);
27 | echo Html::endTag('div');
28 | }
29 |
30 | echo Html::submitButton(\Yii::t('survey', ''), ['class' => 'btn btn-success btn-add-answer survey-question-submit',
31 | 'data-action' => Url::toRoute(['question/add-answer', 'id' => $question->survey_question_id, 'after' => $i])]);
32 | echo Html::submitButton(\Yii::t('survey', ''), ['class' => 'btn btn-danger btn-delete-answer survey-question-submit',
33 | 'data-action' => Url::toRoute(['question/delete-answer', 'id' => $question->survey_question_id, 'answer' => $i]),
34 | 'name' => 'action', 'value' => 'delete-answer'
35 | ]);
36 |
37 | echo Html::tag('br', '');
38 | }
--------------------------------------------------------------------------------
/views/answers/4.php:
--------------------------------------------------------------------------------
1 | field()
17 | foreach ($question->answers as $i => $answer) {
18 |
19 | echo $form->field($answer, "[$question->survey_question_id][$i]survey_answer_name")->input('text',
20 | ['placeholder' => \Yii::t('survey', 'Enter an answer choice')])->label(false);
21 |
22 | echo Html::submitButton(\Yii::t('survey', ''), ['class' => 'btn btn-success btn-add-answer survey-question-submit',
23 | 'data-action' => Url::toRoute(['question/add-answer', 'id' => $question->survey_question_id, 'after' => $i])]);
24 | echo Html::submitButton(\Yii::t('survey', ''), ['class' => 'btn btn-danger btn-delete-answer survey-question-submit',
25 | 'data-action' => Url::toRoute(['question/delete-answer', 'id' => $question->survey_question_id, 'answer' => $i]),
26 | 'name' => 'action', 'value' => 'delete-answer'
27 | ]);
28 |
29 | echo $form->field($answer, "[{$question->survey_question_id}][$i]survey_answer_show_descr",
30 | ['options' => [
31 | 'class' => 'form-group checkbox-inline'
32 | ]])->checkbox(['class' => 'checkbox-updatable']);
33 | echo Html::tag('br', '');
34 |
35 | if ($answer->survey_answer_show_descr) {
36 | echo $form->field($answer, "[{$question->survey_question_id}][$i]survey_answer_descr")->widget(Widget::class, [
37 | 'settings' => [
38 | 'lang' => 'ru',
39 | 'minHeight' => 100,
40 | 'toolbarFixed' => false,
41 | 'imageManagerJson' => Url::toRoute(['question/images-get']),
42 | 'imageUpload' => Url::toRoute(['question/image-upload']),
43 | 'fileManagerJson' => Url::toRoute(['question/files-get']),
44 | 'fileUpload' => Url::toRoute(['question/file-upload']),
45 | 'plugins' => [
46 | 'imagemanager',
47 | 'video',
48 | 'fullscreen',
49 | 'filemanager',
50 | 'fontsize',
51 | 'fontcolor',
52 | 'table',
53 | ]
54 | ]
55 | ])->label(false);
56 | }
57 |
58 | echo Html::tag('br', '');
59 | }
--------------------------------------------------------------------------------
/views/answers/5.php:
--------------------------------------------------------------------------------
1 | answers as $i => $answer) {
16 | switch ($i){
17 | case 0:
18 | $label = 'Min';
19 | break;
20 | case 1:
21 | $label = 'Max';
22 | break;
23 | default:
24 | $label = false;
25 | break;
26 | }
27 | echo $form->field($answer, "[$question->survey_question_id][$i]survey_answer_name", [
28 | 'template' => "{label}{input}\n{error}
"
29 | ])->input('number',
30 | ['placeholder' => \Yii::t('survey', 'Enter an answer choice')])->label($label);
31 |
32 | echo Html::tag('br', '');
33 | }
--------------------------------------------------------------------------------
/views/answers/6.php:
--------------------------------------------------------------------------------
1 | field()
17 | foreach ($question->answers as $i => $answer) {
18 |
19 | echo $form->field($answer, "[$question->survey_question_id][$i]survey_answer_name", [
20 | 'template' => "",
21 | ])->input('text')->label(\Yii::t('survey', 'Label') . ' ' . ($i + 1));
22 |
23 | echo Html::submitButton(\Yii::t('survey', ''), ['class' => 'btn btn-success btn-add-answer survey-question-submit',
24 | 'data-action' => Url::toRoute(['question/add-answer', 'id' => $question->survey_question_id, 'after' => $i])]);
25 | echo Html::submitButton(\Yii::t('survey', ''), ['class' => 'btn btn-danger btn-delete-answer survey-question-submit',
26 | 'data-action' => Url::toRoute(['question/delete-answer', 'id' => $question->survey_question_id, 'answer' => $i]),
27 | 'name' => 'action', 'value' => 'delete-answer'
28 | ]);
29 |
30 | echo Html::tag('br', '');
31 | }
--------------------------------------------------------------------------------
/views/answers/8.php:
--------------------------------------------------------------------------------
1 | field()
17 | foreach ($question->answers as $i => $answer) {
18 |
19 | echo $form->field($answer, "[$question->survey_question_id][$i]survey_answer_name", [
20 | 'template' => "",
21 | ])->input('text')->label(\Yii::t('survey', 'Label') . ' ' . ($i + 1));
22 |
23 | echo Html::submitButton(\Yii::t('survey', ''), ['class' => 'btn btn-success btn-add-answer survey-question-submit',
24 | 'data-action' => Url::toRoute(['question/add-answer', 'id' => $question->survey_question_id, 'after' => $i])]);
25 | echo Html::submitButton(\Yii::t('survey', ''), ['class' => 'btn btn-danger btn-delete-answer survey-question-submit',
26 | 'data-action' => Url::toRoute(['question/delete-answer', 'id' => $question->survey_question_id, 'answer' => $i]),
27 | 'name' => 'action', 'value' => 'delete-answer'
28 | ]);
29 |
30 | echo Html::tag('br', '');
31 | }
--------------------------------------------------------------------------------
/views/answers/_form.php:
--------------------------------------------------------------------------------
1 | render('/answers/' . $question->survey_question_type, ['question' => $question, 'form' => $form]);
--------------------------------------------------------------------------------
/views/answers/view/1.php:
--------------------------------------------------------------------------------
1 | getTotalUserAnswersCount();
19 |
20 | echo Html::beginTag('div', ['class' => 'answers-stat']);
21 | foreach ($question->answers as $i => $answer) {
22 | $count = $answer->getTotalUserAnswersCount();
23 | try {
24 | $percent = ($count / $totalVotesCount) * 100;
25 | }catch (\Exception $e){
26 | $percent = 0;
27 | }
28 | echo $answer->survey_answer_name;
29 | echo Progress::widget([
30 | 'id' => 'progress-' . $answer->survey_answer_id,
31 | 'percent' => $percent,
32 | 'label' => $count,
33 | 'barOptions' => ['class' => 'progress-bar-info init']
34 | ]);
35 | }
36 | echo Html::endTag('div');
37 |
--------------------------------------------------------------------------------
/views/answers/view/10.php:
--------------------------------------------------------------------------------
1 | getTotalUserAnswersCount();
12 |
13 | ?>
14 |
15 |
16 |
17 |
18 | |
19 | |
20 | |
21 | |
22 | |
23 |
24 |
25 |
26 | [
29 | 'value' => '',
30 | 'count' => 0
31 | ],
32 | 3 => [
33 | 'value' => '',
34 | 'count' => 0
35 | ]
36 | ];
37 |
38 | foreach ($question->answers as $i => $answer) {
39 | $count = [
40 | 1 => 0,
41 | 2 => 0,
42 | 3 => 0
43 | ];
44 |
45 | foreach ($answer->userAnswers as $userAnswer) {
46 | $count[$userAnswer->survey_user_answer_value]++;
47 | }
48 |
49 | if ($betterChoice[1]['count'] < $count[1]) {
50 | $betterChoice[1]['value'] = $answer->survey_answer_name;
51 | $betterChoice[1]['count'] = $count[1];
52 | } else if ($count[1] && $betterChoice[1]['count'] == $count[1]) {
53 | $betterChoice[1]['value'] .= \Yii::t('survey', ' or ') . $answer->survey_answer_name;
54 | }
55 |
56 | if ($betterChoice[3]['count'] < $count[1] + $count[3]) {
57 | $betterChoice[3]['value'] = $answer->survey_answer_name;
58 | $betterChoice[3]['count'] = $count[1] + $count[3];
59 | } else if ($count[1] + $count[3] && $betterChoice[1]['count'] == $count[1] + $count[3]) {
60 | $betterChoice[3]['value'] .= \Yii::t('survey', ' or ') . $answer->survey_answer_name;
61 | }
62 |
63 | echo Html::beginTag('tr')
64 | . Html::tag('td', $answer->survey_answer_name)
65 | . Html::tag('td', $count[1])
66 | . Html::tag('td', $count[2])
67 | . Html::tag('td', $count[3])
68 | . Html::tag('td', ($count[1] + $count[3]) . ($count[1] && $count[3] == 0 ? ' *' : ''))
69 | . Html::endTag('tr');
70 | }
71 | ?>
72 |
73 |
74 |
75 | |
76 | |
77 | |
78 | |
79 | |
80 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/views/answers/view/2.php:
--------------------------------------------------------------------------------
1 | getTotalUserAnswersCount();
18 |
19 | echo Html::beginTag('div', ['class' => 'answers-stat']);
20 | foreach ($question->answers as $i => $answer) {
21 | $count = $answer->getTotalUserAnswersCount();
22 | try {
23 | $percent = ($count / $totalVotesCount) * 100;
24 | }catch (\Exception $e){
25 | $percent = 0;
26 | }
27 | echo $answer->survey_answer_name;
28 | echo Progress::widget([
29 | 'id' => 'progress-' . $answer->survey_answer_id,
30 | 'percent' => $percent,
31 | 'label' => $count,
32 | 'barOptions' => ['class' => 'progress-bar-info init']
33 | ]);
34 | }
35 | echo Html::endTag('div');
--------------------------------------------------------------------------------
/views/answers/view/3.php:
--------------------------------------------------------------------------------
1 | getTotalUserAnswersCount();
17 |
18 | echo Html::beginTag('div', ['class' => 'answers-stat']);
19 | foreach ($question->answers as $i => $answer) {
20 | $count = $answer->getTotalUserAnswersCount();
21 | try {
22 | $percent = ($count / $totalVotesCount) * 100;
23 | }catch (\Exception $e){
24 | $percent = 0;
25 | }
26 | echo $answer->survey_answer_name;
27 | echo Progress::widget([
28 | 'id' => 'progress-' . $answer->survey_answer_id,
29 | 'percent' => $percent,
30 | 'label' => $count,
31 | 'barOptions' => ['class' => 'progress-bar-info init']
32 | ]);
33 | }
34 | echo Html::endTag('div');
--------------------------------------------------------------------------------
/views/answers/view/4.php:
--------------------------------------------------------------------------------
1 | 'answers-stat']);
18 | foreach ($question->answers as $i => $answer) {
19 | $average = $answer->getTotalUserAnswersCount();
20 | $average = $average > 0 ? round($average, 1) : 0;
21 | echo Html::label($answer->survey_answer_name) . ' - ' . "average $average";
22 | echo Html::tag('br', '');
23 | }
24 | echo Html::endTag('div');
--------------------------------------------------------------------------------
/views/answers/view/5.php:
--------------------------------------------------------------------------------
1 | 'answers-stat']);
19 |
20 | $average = $question->answers[0]->getTotalUserAnswersCount();
21 | $average = $average > 0 ? round($average, 1) : 0;
22 | echo "average $average";
23 |
24 | echo Html::endTag('div');
--------------------------------------------------------------------------------
/views/answers/view/6.php:
--------------------------------------------------------------------------------
1 | render('/answers/view/' . $question->survey_question_type, ['question' => $question]);
--------------------------------------------------------------------------------
/views/default/_form.php:
--------------------------------------------------------------------------------
1 |
27 |
28 |
29 |
30 | 'survey-name-wrap']);
33 |
34 | \yii\widgets\Pjax::begin([
35 | 'id' => 'form-photo-pjax',
36 | 'timeout' => 0,
37 | 'enablePushState' => false
38 | ]);
39 | $form = ActiveForm::begin([
40 | 'id' => 'survey-photo-form',
41 | 'action' => \yii\helpers\Url::toRoute(['default/update-image', 'id' => $survey->survey_id]),
42 | 'options' => ['class' => 'form-horizontal', 'data-pjax' => true],
43 | // 'enableAjaxValidation' => true,
44 | ]);
45 |
46 | echo UploadCrop::widget([
47 | 'form' => $form,
48 | 'model' => $survey,
49 | 'attribute' => 'imageFile',
50 | 'enableClientValidation' => true,
51 | 'defaultPreviewImage' => $survey->getImage(),
52 | 'jcropOptions' => [
53 | // 'dragMode' => 'none',
54 | 'viewMode' => 2,
55 | 'aspectRatio' => 1,
56 | 'autoCropArea' => 1,
57 | 'rotatable' => true,
58 | 'scalable' => true,
59 | 'zoomable' => true,
60 | 'toggleDragModeOnDblclick' => false
61 | ]
62 | ]);
63 |
64 | ActiveForm::end();
65 | \yii\widgets\Pjax::end();
66 |
67 | echo Editable::widget([
68 | 'model' => $survey,
69 | 'attribute' => 'survey_name',
70 | 'asPopover' => true,
71 | 'header' => 'Name',
72 | 'size' => 'md',
73 | 'formOptions' => [
74 | 'action' => Url::toRoute(['default/update-editable', 'property' => 'survey_name'])
75 | ],
76 | 'additionalData' => ['id' => $survey->survey_id],
77 | 'options' => [
78 | 'class' => 'form-control',
79 | 'placeholder' => 'Enter survey name...',
80 | ]
81 | ]);
82 | echo Html::endTag('div');
83 |
84 |
85 | echo Html::tag('br', '');
86 |
87 | echo Html::beginTag('div', ['class' => 'survey-content-wrap']);
88 | echo Html::beginTag('div', ['class' => 'row']);
89 | echo Html::beginTag('div', ['class' => 'col-md-6']);
90 | echo Html::label(Yii::t('survey', 'Expired at') . ': ', 'survey-survey_expired_at');
91 | echo Editable::widget([
92 | 'model' => $survey,
93 | 'attribute' => 'survey_expired_at',
94 | 'header' => 'Expired at',
95 | 'asPopover' => true,
96 | 'size' => 'md',
97 | 'inputType' => Editable::INPUT_DATETIME,
98 | 'formOptions' => [
99 | 'action' => Url::toRoute(['default/update-editable', 'property' => 'survey_expired_at'])
100 | ],
101 | 'additionalData' => ['id' => $survey->survey_id],
102 | 'options' => [
103 | 'class' => Editable::INPUT_DATETIME,
104 | 'pluginOptions' => [
105 | 'autoclose' => true,
106 | // 'format' => 'd.m.Y H:i'
107 | ],
108 | 'options' => ['placeholder' => 'Expired at']
109 | ],
110 | 'showButtonLabels' => true,
111 | 'submitButton' => [
112 | 'icon' => false,
113 | 'label' => 'OK',
114 | 'class' => 'btn btn-sm btn-primary'
115 | ]
116 | ]);
117 | echo Html::endTag('div'); // col-md-6
118 |
119 | echo Html::beginTag('div', ['class' => 'col-md-6']);
120 | echo Html::label(Yii::t('survey', 'Time to pass') . ': ', 'survey-survey_time_to_pass');
121 | echo Editable::widget([
122 | 'model' => $survey,
123 | 'attribute' => 'survey_time_to_pass',
124 | 'asPopover' => true,
125 | 'header' => 'Time to pass',
126 | 'size' => 'md',
127 | 'formOptions' => [
128 | 'action' => Url::toRoute(['default/update-editable', 'property' => 'survey_time_to_pass'])
129 | ],
130 | 'additionalData' => ['id' => $survey->survey_id],
131 | 'options' => [
132 | 'class' => 'form-control',
133 | 'placeholder' => 'Enter time in minutes...',
134 | 'type' => 'number',
135 | ]
136 | ]);
137 | echo Html::label(Yii::t('survey', 'minutes'));
138 | echo Html::endTag('div'); // col-md-6
139 |
140 | echo Html::endTag('div'); // row
141 |
142 |
143 | Pjax::begin([
144 | 'id' => 'survey-pjax',
145 | 'enablePushState' => false,
146 | 'timeout' => 0,
147 | 'scrollTo' => false,
148 | 'clientOptions' => [
149 | 'type' => 'post',
150 | 'skipOuterContainers' => true,
151 | ]
152 | ]);
153 |
154 | $form = ActiveForm::begin([
155 | 'id' => 'survey-form',
156 | 'action' => Url::toRoute(['default/update', 'id' => $survey->survey_id]),
157 | 'options' => ['class' => 'form-inline', 'data-pjax' => true],
158 | 'enableClientValidation' => false,
159 | 'enableAjaxValidation' => false,
160 | 'fieldConfig' => [
161 | 'template' => "
{label}{input}\n{error}
",
162 | 'labelOptions' => ['class' => ''],
163 | ],
164 | ]);
165 |
166 | echo Html::beginTag('div', ['class' => 'row']);
167 | echo Html::beginTag('div', ['class' => 'col-md-12']);
168 | echo $form->field($survey, "survey_descr", ['template' => "
{label}{input}
",]
169 | )->textarea(['rows' => 3]);
170 | echo Html::tag('div', '', ['class' => 'clearfix']);
171 | echo Html::endTag('div'); // col-md-12
172 | echo Html::endTag('div'); // row
173 |
174 | echo Html::beginTag('div', ['class' => 'row']);
175 | echo Html::beginTag('div', ['class' => 'col-md-3']);
176 | echo $form->field($survey, "survey_is_closed", ['template' => "
{input}{label}
",]
177 | )->checkbox(['class' => 'checkbox danger'], false);
178 | echo Html::tag('div', '', ['class' => 'clearfix']);
179 | echo $form->field($survey, "survey_is_pinned", ['template' => "
{input}{label}
",]
180 | )->checkbox(['class' => 'checkbox'], false);
181 | echo Html::tag('div', '', ['class' => 'clearfix']);
182 | echo $form->field($survey, "survey_is_visible", ['template' => "
{input}{label}
",]
183 | )->checkbox(['class' => 'checkbox'], false);
184 | if ($withUserSearch) {
185 | echo Html::tag('div', '', ['class' => 'clearfix']);
186 | echo $form->field($survey,
187 | "survey_is_private",
188 | ['template' => "
{input}{label}
",]
189 | )->checkbox(['class' => 'checkbox danger'], false);
190 | }
191 | echo Html::endTag('div'); // col-md-3
192 |
193 | echo Html::beginTag('div', ['class' => 'col-md-9']);
194 | echo $form->field($survey, "survey_tags")->input('text', ['placeholder' => 'Comma separated']);
195 | if ($withUserSearch) {
196 | echo Html::tag('div', '', ['class' => 'clearfix']);
197 | echo $form->field($survey, 'restrictedUserIds')->widget(Select2::classname(),
198 | [
199 | 'initValueText' => $survey->restrictedUsernames, // set the initial display text
200 | 'options' => ['placeholder' => \Yii::t('survey', 'Restrict survey to selected user...')],
201 | 'pluginOptions' => [
202 | 'allowClear' => true,
203 | 'minimumInputLength' => 3,
204 | 'language' => [
205 | 'errorLoading' => new JsExpression("function () { return 'Waiting for results...'; }"),
206 | ],
207 | 'ajax' => [
208 | 'url' => Url::toRoute(['default/search-respondents-by-token']),
209 | 'dataType' => 'json',
210 | 'data' => new JsExpression('function(params) { return {token:params.term}; }')
211 | ],
212 | 'multiple' => true,
213 | 'escapeMarkup' => new JsExpression('function (markup) { return markup; }'),
214 | 'templateResult' => new JsExpression('function(city) { return city.text; }'),
215 | 'templateSelection' => new JsExpression('function (city) { return city.text; }'),
216 | ],
217 | 'pluginEvents' => [
218 | 'change' => new JsExpression('function() {
219 | var container = $(this).closest(\'[data-pjax-container]\');
220 | container.find(\'button[type=submit]\').click();
221 | }')
222 | ]
223 | ]);
224 | }
225 | echo Html::endTag('div'); // col-md-9
226 | echo Html::endTag('div'); // row
227 |
228 | echo Html::submitButton('', ['class' => 'hidden']);
229 | echo Html::tag('div', '', ['class' => 'clearfix']);
230 |
231 | ActiveForm::end();
232 |
233 | Pjax::end();
234 | echo Html::endTag('div');
235 |
236 | ?>
237 |
238 |
239 |
240 |
241 | questions as $i => $question) {
243 | echo $this->render('/question/_form', ['question' => $question]);
244 | }
245 | ?>
246 |
247 | 'survey-questions-append']);
249 |
250 | Pjax::begin([
251 | 'id' => 'survey-questions-pjax',
252 | 'enablePushState' => false,
253 | 'timeout' => 0,
254 | 'scrollTo' => false,
255 | 'clientOptions' => [
256 | 'type' => 'post',
257 | 'container' => '#survey-questions-append',
258 | 'skipOuterContainers' => true,
259 | ]
260 | ]);
261 | echo Html::tag('div', Html::a('
' . Yii::t('survey', 'Add question'), Url::toRoute(['question/create', 'id' => $survey->survey_id]), ['class' => 'btn btn-success']),
262 | ['class' => 'text-center survey-btn', 'id' => '']);
263 | echo Html::tag('div', Html::submitButton('
' . Yii::t('survey', 'Save'),
264 | ['class' => 'btn btn-primary', 'data-default-text' => '
' . Yii::t('survey', 'Save')]), ['class' => 'text-center survey-btn', 'id' => 'save', 'data-action' => Url::toRoute(['default/view', 'id' => $survey->survey_id])]);
265 |
266 | Pjax::end(); ?>
267 |
268 |
269 |
270 |
271 | registerJs(<<registerCss(<<registerJs(<<title = Yii::t('survey', 'Create new survey');
20 |
21 |
22 | echo $this->render('_form', [
23 | 'survey' => $survey,
24 | 'withUserSearch' => $withUserSearch
25 | ]);
26 |
27 |
--------------------------------------------------------------------------------
/views/default/index.php:
--------------------------------------------------------------------------------
1 |
20 |
21 | 'btn btn-success pull-right']);
23 |
24 | Pjax::begin([
25 | 'id' => 'survey-index-pjax',
26 | 'enablePushState' => true,
27 | 'timeout' => 0]);
28 |
29 | echo ListView::widget(['id' => 'survey-list',
30 | 'layout' => "{summary}\n{items}\n
{pager}
",
31 | 'dataProvider' => $dataProvider,
32 | 'itemOptions' => ['class' => 'item'],
33 | 'itemView' => function ($model, $key, $index, $widget) {
34 | /** @var $model \onmotion\survey\models\Survey */
35 | $survey = $model;
36 | $image = $survey->getImage();
37 | ob_start();
38 | ?>
39 |
40 |
41 |
42 |
43 |
>
48 |
49 |
54 |
55 |
56 | = $survey->getRespondentsCount() ?>
58 | = $survey->getCompletedRespondentsCount() ?>
60 | = $survey->getQuestions()->count() ?>
62 |
63 |
64 |
67 | '), Url::toRoute(['default/delete', 'id' => $survey->survey_id]), [
69 | 'class' => 'btn btn-danger btn-xs pull-right btn-delete',
70 | 'data-pjax' => 0,
71 | 'role' => 'remote-modal',
72 | 'data-confirm-message' => 'Are you sure?',
73 | 'data-method' => false,// for overide yii data api
74 | 'data-request-method' => 'post',
75 | ]);
76 | ?>
77 |
78 |
79 |
80 |
81 |
82 | Author: = $survey->getAuthorName() ?>
83 | Created At: = \Yii::$app->formatter->asDate($survey->survey_created_at) ?>
84 |
85 |
86 |
87 |
94 |
95 |
96 |
97 | "remote-modal",
99 | "options" => ["class" => "fade "],
100 | "footer" => "", // always need it for jquery plugin
101 | ]) ?>
102 |
103 |
104 | registerJs(<<
17 |
18 |
19 | 'addition-form']);
23 |
24 | echo Html::label(\Yii::t('survey', 'Add respondents'), [], ['class' => 'control-label']);
25 |
26 | $assignUrl = Url::toRoute(['default/assign-user', 'surveyId' => $surveyId]);
27 | $pjaxUrl = Url::toRoute(['default/respondents', 'surveyId' => $surveyId]);
28 | echo Typeahead::widget([
29 | 'name' => 'respondents',
30 | 'id' => 'respondents-typeahead',
31 | 'scrollable' => true,
32 | 'dataset' => [
33 | [
34 | 'display' => 'text',
35 | 'remote' => [
36 | 'url' => Url::toRoute(['default/get-respondents-by-token', 'surveyId' => $surveyId]) . '&token=%QUERY',
37 | 'wildcard' => '%QUERY',
38 | 'rateLimitWait' => 300
39 | ],
40 | 'limit' => 20,
41 | 'templates' => [
42 | 'notFound' => '
' . \Yii::t('survey', 'No result found.') . '
',
43 | 'suggestion' => new \yii\web\JsExpression(<<
'+ data.text +' ';
47 | }else{
48 | return ''+ data.text +'
';
49 | }
50 | }
51 | JS
52 | ),
53 | ],
54 | ]
55 | ],
56 | 'pluginOptions' => [
57 | 'highlight' => true,
58 | 'minLength' => 2,
59 | 'val' => '',
60 | ],
61 | 'pluginEvents' => [
62 | "typeahead:selected" => << ['placeholder' => 'Type some words...'],
79 | ]);
80 | echo Html::endTag('div');
81 | }
82 |
83 | Pjax::begin([
84 | 'id' => 'survey-respondents-pjax',
85 | 'enableReplaceState' => false,
86 | 'enablePushState' => false,
87 | 'timeout' => 0,
88 | 'clientOptions' => [
89 | // 'async' => false
90 | ],
91 | ]);
92 |
93 | ActiveForm::begin([
94 | 'id' => 'survey-respondents-form',
95 | 'action' => Url::toRoute(['default/unassign-user', 'surveyId' => $surveyId]),
96 | 'enableClientValidation' => false,
97 | 'enableAjaxValidation' => false,
98 | 'options' => ['data-pjax' => true],
99 | ]);
100 |
101 | echo ListView::widget([
102 | 'id' => 'survey-respondents-list',
103 | 'layout' => "{summary}
\n{items}\n{pager}
",
104 | 'dataProvider' => $dataProvider,
105 | 'itemOptions' => ['class' => 'item'],
106 | 'itemView' => function ($model, $key, $index, $widget) use ($surveyId) {
107 | /** @var $model \onmotion\survey\models\SurveyStat */
108 | $surveyStat = $model;
109 | ob_start();
110 | ?>
111 |
112 | user->fullname
114 | ?>
115 |
116 |
117 |
118 | '),
120 | [
121 | 'class' => 'btn btn-danger btn-delete-assigned-user user-assign-submit',
122 | 'data-action' => Url::toRoute(['default/unassign-user', 'surveyId' => $surveyId]),
123 | 'name' => 'userId',
124 | 'value' => $surveyStat->survey_stat_user_id
125 | ]);
126 | ?>
127 |
128 |
136 |
137 |
138 |
139 |
--------------------------------------------------------------------------------
/views/default/restrictedUsers.php:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 | 'addition-form']);
21 |
22 | echo Html::label(\Yii::t('survey', 'Add restricted users'), [], ['class' => 'control-label']);
23 |
24 | $assignUrl = Url::toRoute(['default/assign-restricted-user', 'surveyId' => $surveyId]);
25 | $pjaxUrl = Url::toRoute(['default/restricted-users', 'surveyId' => $surveyId]);
26 | echo Typeahead::widget([
27 | 'name' => 'restricted-users',
28 | 'id' => 'restricted-users-typeahead',
29 | 'scrollable' => true,
30 | 'dataset' => [
31 | [
32 | 'display' => 'text',
33 | 'remote' => [
34 | 'url' => Url::toRoute(['default/get-respondents-by-token', 'surveyId' => $surveyId]) . '&token=%QUERY',
35 | 'wildcard' => '%QUERY',
36 | 'rateLimitWait' => 300
37 | ],
38 | 'limit' => 20,
39 | 'templates' => [
40 | 'notFound' => '
' . \Yii::t('survey', 'No result found.') . '
',
41 | 'suggestion' => new \yii\web\JsExpression(<<
'+ data.text +' ';
45 | }else{
46 | return ''+ data.text +'
';
47 | }
48 | }
49 | JS
50 | ),
51 | ],
52 | ]
53 | ],
54 | 'pluginOptions' => [
55 | 'highlight' => true,
56 | 'minLength' => 2,
57 | 'val' => '',
58 | ],
59 | 'pluginEvents' => [
60 | "typeahead:selected" => << ['placeholder' => 'Type some words...'],
77 | ]);
78 | echo Html::endTag('div');
79 |
80 | Pjax::begin([
81 | 'id' => 'survey-restricted-users-pjax',
82 | 'enableReplaceState' => false,
83 | 'enablePushState' => false,
84 | 'timeout' => 0,
85 | 'clientOptions' => [
86 | // 'async' => false
87 | ],
88 | ]);
89 |
90 | ActiveForm::begin([
91 | 'id' => 'survey-restricted-users-form',
92 | 'action' => Url::toRoute(['default/unassign-user', 'surveyId' => $surveyId]),
93 | 'enableClientValidation' => false,
94 | 'enableAjaxValidation' => false,
95 | 'options' => ['data-pjax' => true],
96 | ]);
97 |
98 | echo ListView::widget([
99 | 'id' => 'survey-restricted-users-list',
100 | 'layout' => "{summary}
\n{items}\n{pager}
",
101 | 'dataProvider' => $restrictedUserDataProvider,
102 | 'itemOptions' => ['class' => 'item'],
103 | 'itemView' => function ($model, $key, $index, $widget) use ($surveyId) {
104 | ob_start();
105 | ?>
106 |
107 | fullname
109 | ?>
110 |
111 |
112 |
113 | '),
115 | [
116 | 'class' => 'btn btn-danger btn-delete-assigned-user user-assign-submit',
117 | 'data-action' => Url::toRoute(['default/unassign-restricted-user', 'surveyId' => $surveyId]),
118 | 'name' => 'userId',
119 | 'value' => $model->id
120 | ]);
121 | ?>
122 |
123 |
131 |
132 |
133 |
134 |
--------------------------------------------------------------------------------
/views/default/update.php:
--------------------------------------------------------------------------------
1 | title = Yii::t('survey', 'Update survey');
19 |
20 |
21 | echo $this->render('_form', [
22 | 'survey' => $survey,
23 | 'withUserSearch' => $withUserSearch
24 | ]);
--------------------------------------------------------------------------------
/views/default/view.php:
--------------------------------------------------------------------------------
1 | title = Yii::t('survey', 'Survey') . ' - ' . $survey->survey_name;
27 |
28 | BootstrapPluginAsset::register($this);
29 |
30 |
31 | ?>
32 |
33 |
34 |
35 |
= $survey->survey_name; ?>
36 |
37 |
38 |
41 |
= \Yii::t('survey', 'Number of respondents') ?>: = $survey->getRespondentsCount() ?>
43 |
= \Yii::t('survey', 'Questions') ?>: = $survey->getQuestions()->count() ?>
45 |
= \Yii::t('survey', 'Restricted users') ?>: = $survey->getRestrictedUsersCount() ?>
47 |
48 |
49 |
50 |
51 |
52 |
53 | 'row']);
55 | echo Html::beginTag('div', ['class' => 'col-md-6']);
56 | echo Html::label(Yii::t('survey', 'Expired at') . ': ', 'survey-survey_expired_at');
57 | echo Editable::widget([
58 | 'model' => $survey,
59 | 'attribute' => 'survey_expired_at',
60 | 'header' => 'Expired at',
61 | 'asPopover' => true,
62 | 'size' => 'md',
63 | 'inputType' => Editable::INPUT_DATETIME,
64 | 'formOptions' => [
65 | 'action' => Url::toRoute(['default/update-editable', 'property' => 'survey_expired_at'])
66 | ],
67 | 'additionalData' => ['id' => $survey->survey_id],
68 | 'options' => [
69 | 'class' => Editable::INPUT_DATETIME,
70 | 'pluginOptions' => [
71 | 'autoclose' => true,
72 | // 'format' => 'd.m.Y H:i'
73 | ],
74 | 'options' => ['placeholder' => 'Expired at']
75 | ]
76 | ]);
77 | echo Html::endTag('div');
78 |
79 | echo Html::beginTag('div', ['class' => 'col-md-6']);
80 | echo Html::endTag('div');
81 | echo Html::endTag('div');
82 |
83 | Pjax::begin([
84 | 'id' => 'survey-pjax',
85 | 'enablePushState' => false,
86 | 'timeout' => 0,
87 | 'scrollTo' => false,
88 | 'clientOptions' => [
89 | 'type' => 'post',
90 | 'skipOuterContainers' => true,
91 | ]
92 | ]);
93 |
94 | $form = ActiveForm::begin([
95 | 'id' => 'survey-form',
96 | 'action' => Url::toRoute(['default/update', 'id' => $survey->survey_id]),
97 | 'options' => ['class' => 'form-inline', 'data-pjax' => true],
98 | 'enableClientValidation' => false,
99 | 'enableAjaxValidation' => false,
100 | 'fieldConfig' => [
101 | 'template' => "
{label}{input}\n{error}
",
102 | 'labelOptions' => ['class' => ''],
103 | ],
104 | ]);
105 |
106 | echo Html::beginTag('div', ['class' => 'row']);
107 | echo Html::beginTag('div', ['class' => 'col-md-12']);
108 | echo $form->field($survey, "survey_descr", ['template' => "
{label}{input}
",]
109 | )->textarea(['rows' => 3]);
110 | echo Html::tag('div', '', ['class' => 'clearfix']);
111 | echo Html::endTag('div');
112 | echo Html::endTag('div');
113 |
114 | echo Html::beginTag('div', ['class' => 'row']);
115 | echo Html::beginTag('div', ['class' => 'col-md-3']);
116 | echo $form->field($survey, "survey_is_closed", ['template' => "
{input}{label}
",]
117 | )->checkbox(['class' => 'checkbox danger'], false);
118 | echo Html::tag('div', '', ['class' => 'clearfix']);
119 | echo $form->field($survey, "survey_is_pinned", ['template' => "
{input}{label}
",]
120 | )->checkbox(['class' => 'checkbox'], false);
121 | echo Html::tag('div', '', ['class' => 'clearfix']);
122 | echo $form->field($survey, "survey_is_visible", ['template' => "
{input}{label}
",]
123 | )->checkbox(['class' => 'checkbox'], false);
124 | if ($withUserSearch) {
125 | echo Html::tag('div', '', ['class' => 'clearfix']);
126 | echo $form->field($survey,
127 | "survey_is_private",
128 | ['template' => "
{input}{label}
",]
129 | )->checkbox(['class' => 'checkbox danger'], false);
130 | }
131 | echo Html::endTag('div');
132 |
133 | echo Html::beginTag('div', ['class' => 'col-md-9']);
134 | echo $form->field($survey, "survey_tags")->input('text', ['placeholder' => 'Comma separated']);
135 | echo Html::endTag('div');
136 | echo Html::endTag('div');
137 |
138 | echo Html::submitButton('', ['class' => 'hidden']);
139 | echo Html::tag('div', '', ['class' => 'clearfix']);
140 |
141 | ActiveForm::end();
142 |
143 | Pjax::end();
144 | ?>
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 | questions as $i => $question) {
155 | echo $this->render('/question/_viewForm', ['question' => $question, 'number' => $i]);
156 | }
157 | ?>
158 |
159 |
160 |
161 |
162 |
163 |
164 |
×
165 | survey_id;
168 |
169 | echo $this->render('respondents',
170 | compact('searchModel', 'dataProvider', 'surveyId', 'withUserSearch'));
171 | ?>
172 |
173 |
174 |
175 |
×
176 | survey_id;
179 |
180 | echo $this->render('restrictedUsers',
181 | compact('searchModel', 'restrictedUserDataProvider', 'surveyId', 'withUserSearch'));
182 | ?>
183 |
184 |
185 | registerJs(<<registerJs(<< 'survey-questions-pjax-' . $question->survey_question_id,
26 | 'enablePushState' => false,
27 | 'timeout' => 0,
28 | 'scrollTo' => false,
29 | 'options' => ['class' => 'survey-question-pjax-container'],
30 | // 'reloadCss' => false,
31 | 'clientOptions' => [
32 | 'type' => 'post',
33 | 'skipOuterContainers' => true,
34 | ]
35 | ]);
36 |
37 | $form = ActiveForm::begin([
38 | 'id' => 'survey-questions-form-' . $question->survey_question_id,
39 | 'action' => Url::toRoute(['question/update-and-close', 'id' => $question->survey_question_id]),
40 | 'validationUrl' => Url::toRoute(['question/validate', 'id' => $question->survey_question_id]),
41 | 'options' => ['class' => 'form-inline', 'data-pjax' => true],
42 | 'enableClientValidation' => false,
43 | 'enableAjaxValidation' => true,
44 | 'fieldConfig' => [
45 | 'template' => "{label}{input}\n{error}
",
46 | 'labelOptions' => ['class' => ''],
47 | ],
48 | ]);
49 |
50 | echo Html::beginTag('div', ['class' => 'survey-block', 'id' => 'survey-question-' . $question->survey_question_id]);
51 |
52 | echo Html::beginTag('div', ['class' => 'survey-question-name-wrap']);
53 |
54 | echo $form->field($question, "[{$question->survey_question_id}]survey_question_name")->input('text', ['placeholder' => \Yii::t('survey', 'Enter question name')])->label(false);
55 |
56 | echo Html::a(\Yii::t('survey', ''), Url::toRoute(['question/delete', 'id' => $question->survey_question_id]), [
57 | 'class' => 'btn btn-danger pull-right btn-delete',
58 | ]);
59 | echo Html::submitButton('', ['class' => 'btn btn-success pull-right btn-save-question']);
60 | echo Html::submitButton('', ['class' => 'hidden update-question-btn survey-question-submit', 'data-action' => Url::toRoute(['question/update', 'id' => $question->survey_question_id])]);
61 | echo Html::endTag('div');
62 |
63 | $confirmMessage = \Yii::t('survey', 'Current types are not compatible, all entered data will be deleted. Are you sure?');
64 | echo $form->field($question, "[{$question->survey_question_id}]survey_question_type")->widget(Select2::classname(), [
65 | 'data' => \onmotion\survey\models\SurveyType::getDropdownList(),
66 | 'pluginOptions' => [
67 | 'allowClear' => false
68 | ],
69 | 'pluginEvents' => [
70 |
71 | "select2:selecting" => new \yii\web\JsExpression(<< new \yii\web\JsExpression(<<field($question, "[{$question->survey_question_id}]survey_question_show_descr")->checkbox(['class' => 'checkbox-updatable']);
111 | echo Html::tag('br', '');
112 |
113 | if ($question->survey_question_show_descr) {
114 | echo $form->field($question, "[{$question->survey_question_id}]survey_question_descr")->widget(Widget::class, [
115 | 'settings' => [
116 | 'lang' => 'ru',
117 | 'minHeight' => 200,
118 | 'toolbarFixed' => false,
119 | 'imageManagerJson' => Url::toRoute(['question/images-get']),
120 | 'imageUpload' => Url::toRoute(['question/image-upload']),
121 | 'fileManagerJson' => Url::toRoute(['question/files-get']),
122 | 'fileUpload' => Url::toRoute(['question/file-upload']),
123 | 'plugins' => [
124 | 'imagemanager',
125 | 'video',
126 | 'fullscreen',
127 | 'filemanager',
128 | 'fontsize',
129 | 'fontcolor',
130 | 'table',
131 | ]
132 | ]
133 | ])->label(false);
134 | }
135 |
136 | echo Html::beginTag('div', ['class' => 'answers-container', 'id' => 'survey-answers-' . $question->survey_question_id]);
137 | if (isset($question->survey_question_type)) {
138 | echo $this->render('/answers/_form', ['question' => $question, 'form' => $form]);
139 | }
140 |
141 | echo Html::endTag('div');
142 |
143 | echo Html::tag('hr', '');
144 | echo $form->field($question, "[{$question->survey_question_id}]survey_question_can_skip")->checkbox();
145 | if (in_array($question->survey_question_type, [
146 | SurveyType::TYPE_MULTIPLE,
147 | SurveyType::TYPE_ONE_OF_LIST,
148 | SurveyType::TYPE_DROPDOWN
149 | ])) {
150 | echo Html::tag('br', '');
151 | echo $form->field($question, "[{$question->survey_question_id}]survey_question_is_scorable")->checkbox(['class' => 'checkbox-updatable']);
152 | }
153 | ?>
154 |
157 | 'survey-block', 'id' => 'survey-question-' . $question->survey_question_id]);
27 |
28 | echo Html::beginTag('div', ['class' => 'survey-question-name-wrap']);
29 | echo ($number + 1) . '. ' . $question->survey_question_name;
30 | echo Html::endTag('div');
31 |
32 |
33 | echo Html::beginTag('div', ['class' => 'survey-question-descr-wrap']);
34 | if ($question->survey_question_show_descr) {
35 | echo $question->survey_question_descr;
36 | }
37 | echo Html::endTag('div');
38 |
39 |
40 | echo Html::beginTag('div', ['class' => 'answers-container', 'id' => 'survey-answers-' . $question->survey_question_id]);
41 | if (isset($question->survey_question_type)) {
42 | echo $this->render('/answers/view/_form', ['question' => $question]);
43 | }
44 |
45 | echo Html::endTag('div');
46 |
47 | echo Html::tag('hr', '');
48 |
49 | ?>
50 |
53 | 'survey-questions-pjax-' . $question->survey_question_id,
20 | 'enablePushState' => false,
21 | 'timeout' => 0,
22 | 'scrollTo' => false,
23 | 'clientOptions' => [
24 | 'type' => 'post',
25 | 'skipOuterContainers' => true,
26 | ]
27 | ]);
28 |
29 | echo Html::beginTag('div', ['class' => 'survey-block', 'id' => 'survey-question-' . $question->survey_question_id]);
30 | echo Html::beginTag('div', ['class' => 'survey-question-view-wrap']);
31 |
32 | echo Html::tag('h4', $question->survey_question_name);
33 |
34 | echo Html::a(\Yii::t('survey', ''), Url::toRoute(['question/edit', 'id' => $question->survey_question_id]), [
35 | 'class' => 'btn btn-info pull-right btn-edit',
36 | ]);
37 | echo Html::endTag('div');
38 | echo Html::endTag('div');
39 |
40 | Pjax::end();
--------------------------------------------------------------------------------
/views/widget/answers/1.php:
--------------------------------------------------------------------------------
1 | userAnswers;
19 |
20 | foreach ($question->answers as $i => $answer) {
21 | $userAnswer = $userAnswers[$answer->survey_answer_id] ?? (new SurveyUserAnswer());
22 |
23 | $label = '' . $answer->survey_answer_name . '
';
24 |
25 |
26 | if ($answer->survey_answer_show_descr) {
27 | $label .= "
$answer->survey_answer_descr
";
28 | }
29 | $label .= '
';
30 |
31 | echo $form->field($userAnswer, "[$question->survey_question_id][$answer->survey_answer_id]survey_user_answer_value",
32 | [
33 | 'template' => "{input}{label}
\n{hint}\n{error}",
34 | 'labelOptions' => ['class' => 'css-label', 'label' => $label],
35 | ]
36 | )->checkbox(['class' => 'css-checkbox', 'disabled' => $readonly], false);
37 |
38 | echo Html::tag('br', '');
39 | }
--------------------------------------------------------------------------------
/views/widget/answers/10.php:
--------------------------------------------------------------------------------
1 | userAnswers;
19 |
20 | $ddList = [
21 | 1 => \Yii::t('survey', 'Available'),
22 | 2 => \Yii::t('survey', 'Unavailable'),
23 | 3 => \Yii::t('survey', 'If needed'),
24 | ];
25 |
26 | foreach ($question->answers as $i => $answer) {
27 | $userAnswer = $userAnswers[$answer->survey_answer_id] ?? (new SurveyUserAnswer());
28 |
29 | $label = '' . $answer->survey_answer_name . '
';
30 |
31 | if ($answer->survey_answer_show_descr) {
32 | $label .= '
' . $answer->survey_answer_descr;
33 | }
34 | $label .= '
';
35 |
36 | echo Html::beginTag('div', ['class' => 'answer-item']);
37 |
38 | echo Html::tag('div', $form->field($userAnswer, "[$question->survey_question_id][$answer->survey_answer_id]survey_user_answer_value",[
39 | 'template' => "{input}{label}\n{hint}\n{error}",
40 | ])
41 | ->dropDownList($ddList, ['encode' => false, 'prompt' => \Yii::t('survey', 'Select...'), 'disabled' => $readonly])->label(false));
42 | echo $label;
43 | echo Html::endTag('div');
44 |
45 | // echo Html::tag('br', '');
46 | }
--------------------------------------------------------------------------------
/views/widget/answers/2.php:
--------------------------------------------------------------------------------
1 | userAnswers;
18 | $userAnswer = !empty(current($userAnswers)) ? current($userAnswers) : (new SurveyUserAnswer());
19 | $radioList = [];
20 |
21 | foreach ($question->answers as $i => $answer) {
22 |
23 | $radioList[$answer->survey_answer_id] = '' . $answer->survey_answer_name . '
';
24 | if ($answer->survey_answer_show_descr) {
25 | $radioList[$answer->survey_answer_id] .= '
' . $answer->survey_answer_descr;
26 | }
27 | $radioList[$answer->survey_answer_id] .= '
';
28 | }
29 |
30 | echo $form->field($userAnswer, "[$question->survey_question_id]survey_user_answer_value",
31 | ['template' => "{label}{input}
\n{hint}\n{error}"])
32 | ->radioList($radioList, ['encode' => false,
33 | 'item' => function ($index, $label, $name, $checked, $value) use ($readonly) {
34 | $id = uniqid('radio-');
35 | return Html::radio($name, $checked, ['value' => $value, 'class' => 'css-radio', 'id' => $id, 'disabled' => $readonly]) . "';
36 | }
37 | ])->label(false);
38 |
39 | echo Html::tag('br', '');
--------------------------------------------------------------------------------
/views/widget/answers/3.php:
--------------------------------------------------------------------------------
1 | userAnswers;
17 | $userAnswer = !empty(current($userAnswers)) ? current($userAnswers) : (new SurveyUserAnswer()) ;
18 | $ddList = [];
19 |
20 | foreach ($question->answers as $i => $answer) {
21 | $ddList[$answer->survey_answer_id] = $answer->survey_answer_name;
22 | }
23 |
24 | echo $form->field($userAnswer, "[$question->survey_question_id]survey_user_answer_value")->dropDownList($ddList,
25 | ['encode' => false, 'prompt' => \Yii::t('survey', 'Select...'), 'disabled' => $readonly])->label(false);
26 | echo Html::tag('div', '', ['class' => 'clearfix']);
--------------------------------------------------------------------------------
/views/widget/answers/4.php:
--------------------------------------------------------------------------------
1 | userAnswers;
19 |
20 | $ddList = [];
21 | for ($i = 1, $answersCnt = count($question->answers); $i <= $answersCnt; ++$i){
22 | $ddList[$i] = $i;
23 | }
24 |
25 | foreach ($question->answers as $i => $answer) {
26 | $userAnswer = $userAnswers[$answer->survey_answer_id] ?? (new SurveyUserAnswer());
27 |
28 | $label = '' . $answer->survey_answer_name . '
';
29 |
30 | if ($answer->survey_answer_show_descr) {
31 | $label .= '
' . $answer->survey_answer_descr;
32 | }
33 | $label .= '
';
34 |
35 | echo Html::beginTag('div', ['class' => 'answer-item']);
36 |
37 | echo Html::tag('div', $form->field($userAnswer, "[$question->survey_question_id][$answer->survey_answer_id]survey_user_answer_value",[
38 | 'template' => "{input}{label}\n{hint}\n{error}",
39 | ])
40 | ->dropDownList($ddList, ['encode' => false, 'prompt' => \Yii::t('survey', 'Select...'), 'disabled' => $readonly])->label(false));
41 | echo $label;
42 | echo Html::endTag('div');
43 |
44 | // echo Html::tag('br', '');
45 | }
--------------------------------------------------------------------------------
/views/widget/answers/5.php:
--------------------------------------------------------------------------------
1 | userAnswers;
20 | $userAnswer = !empty(current($userAnswers)) ? current($userAnswers) : (new SurveyUserAnswer());
21 | $min = isset($question->answers[0]->survey_answer_name) ? intval($question->answers[0]->survey_answer_name) : 0;
22 | $max = isset($question->answers[1]->survey_answer_name) ? intval($question->answers[1]->survey_answer_name) : 100;
23 |
24 | $userAnswer->survey_user_answer_value = intval($userAnswer->survey_user_answer_value);
25 |
26 | echo $form->field($userAnswer, "[$question->survey_question_id]survey_user_answer_value",
27 | ['template' => '"])->widget(Slider::classname(), [
28 | 'id' => 'slider',
29 | 'sliderColor' => Slider::TYPE_GREY,
30 | 'pluginOptions' => [
31 | 'min' => $min,
32 | 'max' => $max,
33 | 'now' => 0,
34 | 'step' => 1,
35 | 'range' => false,
36 | ],
37 | 'options' => [
38 | 'disabled' => $readonly,
39 | ],
40 | ])->label(false);
41 |
42 |
--------------------------------------------------------------------------------
/views/widget/answers/6.php:
--------------------------------------------------------------------------------
1 | userAnswers;
20 | $userAnswer = !empty(current($userAnswers)) ? current($userAnswers) : (new SurveyUserAnswer()) ;
21 |
22 | echo $form->field($userAnswer, "[$question->survey_question_id]survey_user_answer_value")->textInput(
23 | ['placeholder' => \Yii::t('survey', 'Enter your answer here'), 'disabled' => $readonly])->label(\Yii::t('survey', 'Answer'));
24 |
25 |
--------------------------------------------------------------------------------
/views/widget/answers/7.php:
--------------------------------------------------------------------------------
1 | userAnswers;
19 |
20 | foreach ($question->answers as $i => $answer) {
21 | $userAnswer = $userAnswers[$answer->survey_answer_id] ?? (new SurveyUserAnswer());
22 |
23 | echo $form->field($userAnswer, "[$question->survey_question_id][$answer->survey_answer_id]survey_user_answer_value")->input('text',
24 | ['placeholder' => \Yii::t('survey', 'Enter your answer here'), 'disabled' => $readonly])->label($answer->survey_answer_name);
25 |
26 | echo Html::tag('div', '', ['class' => 'clearfix']);
27 | }
--------------------------------------------------------------------------------
/views/widget/answers/8.php:
--------------------------------------------------------------------------------
1 | userAnswers;
20 | $userAnswer = !empty(current($userAnswers)) ? current($userAnswers) : (new SurveyUserAnswer()) ;
21 |
22 | echo $form->field($userAnswer, "[$question->survey_question_id]survey_user_answer_text")->textarea(
23 | ['placeholder' => \Yii::t('survey', 'Enter your answer here'), 'rows' => 6, 'disabled' => $readonly])->label(\Yii::t('survey', 'Answer'));
24 |
25 |
--------------------------------------------------------------------------------
/views/widget/answers/9.php:
--------------------------------------------------------------------------------
1 | userAnswers;
20 |
21 | foreach ($question->answers as $i => $answer) {
22 | $userAnswer = $userAnswers[$answer->survey_answer_id] ?? (new SurveyUserAnswer());
23 |
24 | echo $form->field($userAnswer, "[$question->survey_question_id][$answer->survey_answer_id]survey_user_answer_value",
25 | [
26 | 'template' => "{input}{label}\n{hint}\n{error}
",
27 | 'labelOptions' => ['class' => 'css-label answer-text'],
28 | ]
29 | )->widget(DatePicker::classname(), [
30 | 'options' => ['placeholder' => 'Enter event time ...'],
31 | 'removeButton' => false,
32 | 'disabled' => $readonly,
33 | 'pluginOptions' => [
34 | 'format' => 'dd-MM-yyyy',
35 | 'autoclose' => true
36 | ]
37 | ])->label($answer->survey_answer_name);
38 | // echo Html::label($answer->survey_answer_name);
39 |
40 | echo Html::tag('div', '', ['class' => 'clearfix']);
41 | }
--------------------------------------------------------------------------------
/views/widget/answers/_form.php:
--------------------------------------------------------------------------------
1 | render('@surveyRoot/views/widget/answers/' . $question->survey_question_type, ['question' => $question, 'form' => $form, 'readonly' => $readonly]);
--------------------------------------------------------------------------------
/views/widget/default/closed.php:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/views/widget/default/index.php:
--------------------------------------------------------------------------------
1 | survey_stat_is_done) {
28 | $status = 'Completed';
29 | $statusClass = 'is-done';
30 | } else {
31 | $statusClass = $survey->getStatus();
32 | switch ($statusClass) {
33 | case 'active':
34 | $status = 'Active';
35 | break;
36 | case 'expired':
37 | $status = 'Expired';
38 | break;
39 | case 'closed':
40 | $status = 'Closed';
41 | break;
42 | default:
43 | $status = 'undefined';
44 | break;
45 | }
46 | }
47 | ?>
48 |
49 |
132 | registerJs(<<survey_id});
137 | });
138 | JS
139 | );
--------------------------------------------------------------------------------
/views/widget/default/success.php:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/views/widget/default/unavailable.php:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/views/widget/question/_form.php:
--------------------------------------------------------------------------------
1 | 'survey-questions-pjax-' . $question->survey_question_id,
28 | 'enablePushState' => false,
29 | 'timeout' => 0,
30 | 'scrollTo' => false,
31 | 'options' => ['class' => 'survey-question-pjax-container'],
32 | 'clientOptions' => [
33 | 'type' => 'post',
34 | 'skipOuterContainers' => true,
35 | // 'async' => false,
36 | ]
37 | ]);
38 |
39 | $form = ActiveForm::begin([
40 | 'id' => 'survey-questions-form-' . $question->survey_question_id,
41 | 'action' => Url::toRoute(['/survey/question/submit-answer', 'id' => $question->survey_question_id, 'n' => $number]),
42 | 'validationUrl' => Url::toRoute(['/survey/question/validate', 'id' => $question->survey_question_id]),
43 | 'options' => ['class' => 'form-inline question-form', 'data-pjax' => true],
44 | 'enableClientValidation' => false,
45 | 'enableAjaxValidation' => true,
46 | 'validateOnBlur' => false,
47 | 'validateOnSubmit' => true,
48 | 'fieldConfig' => [
49 | 'template' => "{label}{input}\n{error}
",
50 | 'labelOptions' => ['class' => ''],
51 | ],
52 | ]);
53 |
54 | echo Html::beginTag('div', ['class' => 'survey-block', 'id' => 'survey-question-' . $question->survey_question_id]);
55 |
56 | echo Html::beginTag('div', ['class' => 'survey-question-name-wrap']);
57 | echo Html::tag('h4', ($number + 1) . '. ' . $question->survey_question_name);
58 | echo Html::endTag('div');
59 |
60 | if ($question->survey_question_show_descr) {
61 | echo Html::beginTag('div', ['class' => 'survey-question-descr-wrap']);
62 | echo $question->survey_question_descr;
63 | echo Html::endTag('div');
64 | }
65 |
66 |
67 | echo Html::beginTag('div', ['class' => 'answers-container', 'id' => 'survey-answers-' . $question->survey_question_id]);
68 | if (isset($question->survey_question_type)) {
69 | echo $this->render('@surveyRoot/views/widget/answers/_form', ['question' => $question, 'form' => $form, 'readonly' => $readonly]);
70 | }
71 |
72 | echo Html::endTag('div');
73 |
74 | echo Html::tag('div', Html::submitButton('DONE', ['class' => 'btn btn-primary btn-submit hidden animated']), ['class' => 'card-footer']);
75 |
76 | //echo $form->errorSummary([$question]);
77 |
78 | ?>
79 |
82 | userAnswers;
39 | if ($question->survey_question_type === SurveyType::TYPE_MULTIPLE
40 | || $question->survey_question_type === SurveyType::TYPE_RANKING
41 | || $question->survey_question_type === SurveyType::TYPE_MULTIPLE_TEXTBOX
42 | || $question->survey_question_type === SurveyType::TYPE_CALENDAR
43 | ) {
44 | if (count($userAnswers) < 2) {
45 | return false;
46 | }
47 | foreach ($question->answers as $i => $answer) {
48 | $userAnswer = $userAnswers[$answer->survey_answer_id];
49 | $userAnswer->validate();
50 | foreach ($userAnswer->getErrors() as $attribute => $errors) {
51 | return false;
52 | }
53 | $question->validateMultipleAnswer();
54 | foreach ($question->userAnswers as $userAnswer) {
55 | foreach ($userAnswer->getErrors() as $attribute => $errors) {
56 | return false;
57 | }
58 | }
59 | }
60 | } elseif ($question->survey_question_type === SurveyType::TYPE_ONE_OF_LIST
61 | || $question->survey_question_type === SurveyType::TYPE_DROPDOWN
62 | || $question->survey_question_type === SurveyType::TYPE_SLIDER
63 | || $question->survey_question_type === SurveyType::TYPE_SINGLE_TEXTBOX
64 | || $question->survey_question_type === SurveyType::TYPE_COMMENT_BOX
65 | || $question->survey_question_type === SurveyType::TYPE_DATE_TIME
66 | ) {
67 | if (empty(current($userAnswers))) {
68 | return false;
69 | }
70 | $userAnswer = current($userAnswers);
71 | $userAnswer->validate();
72 | foreach ($userAnswer->getErrors() as $attribute => $errors) {
73 | return false;
74 | }
75 | }
76 |
77 | return true;
78 | }
79 |
80 | public function actionDone()
81 | {
82 | $id = \Yii::$app->request->post('id');
83 | if ($id < 0) {
84 | throw new UserException('Wrong survey id defined');
85 | }
86 | $survey = $this->findModel($id);
87 | $stat = SurveyStat::findOne(['survey_stat_survey_id' => $id, 'survey_stat_user_id' => \Yii::$app->user->getId()]);
88 | if ($stat === null) {
89 | throw new UserException('The requested survey stat does not exist.');
90 | } elseif ($stat->survey_stat_is_done) {
91 | throw new UserException('The survey has already been completed.');
92 | }
93 | foreach ($survey->questions as $question) {
94 | if (!$this->validateQuestion($question)) {
95 | throw new UserException('An error has been occurred during validating.');
96 | }
97 | }
98 | //all validation is passed.
99 | $stat->survey_stat_is_done = true;
100 | $stat->survey_stat_ended_at = new Expression("NOW()");
101 | $stat->save(false);
102 |
103 | \Yii::$app->response->format = Response::FORMAT_JSON;
104 | return [
105 | 'title' => '' . \Yii::t('survey', 'Thank you!'),
106 | 'content' => $this->renderPartial('@surveyRoot/views/widget/default/success', ['survey' => $survey]),
107 | 'footer' =>
108 | Html::button('Ok', ['class' => 'btn btn-default pull-left', 'data-dismiss' => "modal"])
109 | ];
110 | }
111 |
112 | protected function findModel($id)
113 | {
114 | if (($model = Survey::findOne($id)) !== null) {
115 | return $model;
116 | } else {
117 | throw new NotFoundHttpException('The requested page does not exist.');
118 | }
119 | }
120 |
121 |
122 | }
123 |
--------------------------------------------------------------------------------
/widgetControllers/QuestionController.php:
--------------------------------------------------------------------------------
1 | user->getId(), $question->survey->survey_id);
38 | //не работаем с завершенными опросами
39 | if ($stat->survey_stat_is_done) {
40 | return false;
41 | }
42 | $post = \Yii::$app->request->post();
43 |
44 | $result = [];
45 |
46 | \Yii::$app->response->format = Response::FORMAT_JSON;
47 |
48 | $answersData = ArrayHelper::getValue($post, "SurveyUserAnswer.{$question->survey_question_id}");
49 | $userAnswers = $question->userAnswers;
50 |
51 | if (!empty($answersData)) {
52 | if ($question->survey_question_type === SurveyType::TYPE_MULTIPLE
53 | || $question->survey_question_type === SurveyType::TYPE_RANKING
54 | || $question->survey_question_type === SurveyType::TYPE_MULTIPLE_TEXTBOX
55 | || $question->survey_question_type === SurveyType::TYPE_DATE_TIME
56 | || $question->survey_question_type === SurveyType::TYPE_CALENDAR
57 | ) {
58 | foreach ($question->answers as $i => $answer) {
59 | if (!$question->survey->isAccessibleByCurrentUser) {
60 | die(['lkj']);
61 | }
62 |
63 | $userAnswer = isset($userAnswers[$answer->survey_answer_id]) ? $userAnswers[$answer->survey_answer_id] : (new SurveyUserAnswer([
64 | 'survey_user_answer_user_id' => \Yii::$app->user->getId(),
65 | 'survey_user_answer_survey_id' => $question->survey_question_survey_id,
66 | 'survey_user_answer_question_id' => $question->survey_question_id,
67 | 'survey_user_answer_answer_id' => $answer->survey_answer_id
68 | ]));
69 | if ($userAnswer->load($answersData[$answer->survey_answer_id], '')) {
70 | $userAnswer->validate();
71 | foreach ($userAnswer->getErrors() as $attribute => $errors) {
72 | $result["surveyuseranswer-{$question->survey_question_id}-{$answer->survey_answer_id}-{$attribute}"] = $errors;
73 | }
74 | $userAnswer->save();
75 | }
76 | }
77 | $question->refresh();
78 | $question->validateMultipleAnswer();
79 | foreach ($question->userAnswers as $userAnswer) {
80 | foreach ($userAnswer->getErrors() as $attribute => $errors) {
81 | $result["surveyuseranswer-{$question->survey_question_id}-{$userAnswer->survey_user_answer_answer_id}-{$attribute}"] = $errors;
82 | }
83 | }
84 | } elseif ($question->survey_question_type === SurveyType::TYPE_ONE_OF_LIST
85 | || $question->survey_question_type === SurveyType::TYPE_DROPDOWN
86 | || $question->survey_question_type === SurveyType::TYPE_SLIDER
87 | || $question->survey_question_type === SurveyType::TYPE_SINGLE_TEXTBOX
88 | || $question->survey_question_type === SurveyType::TYPE_COMMENT_BOX
89 | ) {
90 | $userAnswer = !empty(current($userAnswers)) ? current($userAnswers) : (new SurveyUserAnswer([
91 | 'survey_user_answer_user_id' => \Yii::$app->user->getId(),
92 | 'survey_user_answer_survey_id' => $question->survey_question_survey_id,
93 | 'survey_user_answer_question_id' => $question->survey_question_id,
94 | ]));
95 | if ($userAnswer->load($answersData, '')) {
96 | $userAnswer->validate();
97 | foreach ($userAnswer->getErrors() as $attribute => $errors) {
98 | $result["surveyuseranswer-{$question->survey_question_id}-{$attribute}"] = $errors;
99 | }
100 | $userAnswer->save();
101 | }
102 | }
103 | }
104 |
105 | return $result;
106 | }
107 |
108 | public function actionValidate($id)
109 | {
110 | $question = $this->findModel($id);
111 | return $this->validate($question);
112 | }
113 |
114 | public function actionSubmitAnswer($id, $n)
115 | {
116 | $question = $this->findModel($id);
117 | $this->validate($question);
118 |
119 | return $this->renderAjax('@surveyRoot/views/widget/question/_form', ['question' => $question, 'number' => $n]);
120 | }
121 |
122 |
123 | protected function findModel($id)
124 | {
125 | if (($model = SurveyQuestion::findOne($id)) !== null) {
126 | return $model;
127 | } else {
128 | throw new NotFoundHttpException('The requested page does not exist.');
129 | }
130 | }
131 |
132 | protected function findSurveyModel($id)
133 | {
134 | if (($model = Survey::findOne($id)) !== null) {
135 | return $model;
136 | } else {
137 | throw new NotFoundHttpException('The requested page does not exist.');
138 | }
139 | }
140 |
141 | protected function findTypeModel($id)
142 | {
143 | if (($model = SurveyType::findOne($id)) !== null) {
144 | return $model;
145 | } else {
146 | throw new NotFoundHttpException('The requested page does not exist.');
147 | }
148 | }
149 | }
150 |
--------------------------------------------------------------------------------