@touchpoll/tp-survey 0.0.48 → 0.0.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -199,21 +199,28 @@ const answerSSValidator = () => (control) => {
|
|
|
199
199
|
//ошибок нет, всё корректно
|
|
200
200
|
return null;
|
|
201
201
|
};
|
|
202
|
-
const answerMSValidator = (
|
|
203
|
-
//
|
|
202
|
+
const answerMSValidator = (visibleAlternativeList, minCount = 1, maxCount = 0) => (control) => {
|
|
203
|
+
//visibleAlternativeList - альтернативы на экране, если их 0, то смысла показывать вопрос нет
|
|
204
204
|
//minCount - Минимальное количество ответов, которое может выбрать респондент, по умолчанию 1.
|
|
205
205
|
//maxCount - Максимальное количество ответов, которые может выбрать респондент. Если указано 0, количество не ограничено. По умолчанию 0
|
|
206
|
-
if (
|
|
206
|
+
if (visibleAlternativeList.length === 0) {
|
|
207
207
|
return null;
|
|
208
208
|
}
|
|
209
209
|
//ответ не массив, такого быть не может, это ошибка
|
|
210
210
|
if (!Array.isArray(control.value)) {
|
|
211
211
|
return { answerMsAnswerType: true };
|
|
212
212
|
}
|
|
213
|
+
//Проблема минимального количества ответов - если доступных на экране альтернатив меньше, чем настройка "минимальное количество ответов", то это нужно учитывать.
|
|
214
|
+
//Поэтому вычисляем минимально возможное количество ответов, которое может выбрать респондент и если оно меньше значения из настроек, возьмем его.
|
|
215
|
+
let minPossibleCount = minCount;
|
|
216
|
+
if (control.value.length > 0) {
|
|
217
|
+
const currentAlternativeGroup = visibleAlternativeList.find(alternative => alternative.Value === control.value[0])?.GroupNo ?? 1;
|
|
218
|
+
minPossibleCount = Math.min(visibleAlternativeList.filter(alternative => alternative.GroupNo === currentAlternativeGroup).length, minCount);
|
|
219
|
+
}
|
|
213
220
|
//количество ответов
|
|
214
221
|
const count = control.value.length;
|
|
215
222
|
//проверяем minCount
|
|
216
|
-
if (count <
|
|
223
|
+
if (count < minPossibleCount) {
|
|
217
224
|
return { answerMsMinCount: true };
|
|
218
225
|
}
|
|
219
226
|
//проверяем maxCount
|
|
@@ -546,7 +553,6 @@ class AlternativesContainerDirective {
|
|
|
546
553
|
const deltaHorizontal = (containerWidthFull - width * columnCount - horizontalDistance * (columnCount - 1)) / 2 - defaultHorizontalPadding;
|
|
547
554
|
let rowNum = -1;
|
|
548
555
|
let colNum = 0;
|
|
549
|
-
console.log(containerHeightFull, height * rowCount, verticalDistance, (rowCount - 1));
|
|
550
556
|
alternatives.forEach((alt, index) => {
|
|
551
557
|
let left = 0;
|
|
552
558
|
let top = 0;
|
|
@@ -954,7 +960,7 @@ class AnswerOLComponent extends AnswerMasterComponent {
|
|
|
954
960
|
useExisting: forwardRef(() => AnswerOLComponent),
|
|
955
961
|
multi: true
|
|
956
962
|
},
|
|
957
|
-
], usesInheritance: true, ngImport: i0, template: "<div class=\"container-main\">\r\n @if (telephoneInput()) {\r\n <mat-form-field appearance=\"outline\">\r\n <input\r\n type=\"text\"\r\n inputmode=\"numeric\"\r\n matInput\r\n [formControl]=\"control\" tpSurveyFocusAndSelect>\r\n <span matTextPrefix>+380 </span>\r\n </mat-form-field>\r\n @if(canSkip()) {\r\n <button mat-button (click)=\"skipClick()\">\u041F\u0440\u043E\u043F\u0443\u0441\u0442\u0438\u0442\u0438</button>\r\n }\r\n\r\n } @else {\r\n <mat-form-field appearance=\"outline\" class=\"input-text\">\r\n <textarea rows=\"10\" matInput [formControl]=\"control\" tpSurveyFocusAndSelect></textarea>\r\n </mat-form-field>\r\n
|
|
963
|
+
], usesInheritance: true, ngImport: i0, template: "<div class=\"container-main\">\r\n @if (telephoneInput()) {\r\n <mat-form-field appearance=\"outline\">\r\n <input\r\n type=\"text\"\r\n inputmode=\"numeric\"\r\n matInput\r\n [formControl]=\"control\" tpSurveyFocusAndSelect>\r\n <span matTextPrefix>+380 </span>\r\n </mat-form-field>\r\n @if(canSkip()) {\r\n <button mat-button (click)=\"skipClick()\">\u041F\u0440\u043E\u043F\u0443\u0441\u0442\u0438\u0442\u0438</button>\r\n }\r\n\r\n } @else {\r\n <mat-form-field appearance=\"outline\" class=\"input-text\">\r\n <textarea rows=\"10\" matInput [formControl]=\"control\" tpSurveyFocusAndSelect></textarea>\r\n </mat-form-field>\r\n }\r\n</div>\r\n", styles: [":host{width:100%}.container-main{display:flex;width:100%;justify-content:center;align-items:center;flex-flow:column;gap:2em;padding:0 2em;box-sizing:border-box}.input-text{width:100%}\n"], dependencies: [{ kind: "directive", type: FocusAndSelectDirective, selector: "[tpSurveyFocusAndSelect]" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }] }); }
|
|
958
964
|
}
|
|
959
965
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.7", ngImport: i0, type: AnswerOLComponent, decorators: [{
|
|
960
966
|
type: Component,
|
|
@@ -972,7 +978,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.1.7", ngImpor
|
|
|
972
978
|
useExisting: forwardRef(() => AnswerOLComponent),
|
|
973
979
|
multi: true
|
|
974
980
|
},
|
|
975
|
-
], template: "<div class=\"container-main\">\r\n @if (telephoneInput()) {\r\n <mat-form-field appearance=\"outline\">\r\n <input\r\n type=\"text\"\r\n inputmode=\"numeric\"\r\n matInput\r\n [formControl]=\"control\" tpSurveyFocusAndSelect>\r\n <span matTextPrefix>+380 </span>\r\n </mat-form-field>\r\n @if(canSkip()) {\r\n <button mat-button (click)=\"skipClick()\">\u041F\u0440\u043E\u043F\u0443\u0441\u0442\u0438\u0442\u0438</button>\r\n }\r\n\r\n } @else {\r\n <mat-form-field appearance=\"outline\" class=\"input-text\">\r\n <textarea rows=\"10\" matInput [formControl]=\"control\" tpSurveyFocusAndSelect></textarea>\r\n </mat-form-field>\r\n
|
|
981
|
+
], template: "<div class=\"container-main\">\r\n @if (telephoneInput()) {\r\n <mat-form-field appearance=\"outline\">\r\n <input\r\n type=\"text\"\r\n inputmode=\"numeric\"\r\n matInput\r\n [formControl]=\"control\" tpSurveyFocusAndSelect>\r\n <span matTextPrefix>+380 </span>\r\n </mat-form-field>\r\n @if(canSkip()) {\r\n <button mat-button (click)=\"skipClick()\">\u041F\u0440\u043E\u043F\u0443\u0441\u0442\u0438\u0442\u0438</button>\r\n }\r\n\r\n } @else {\r\n <mat-form-field appearance=\"outline\" class=\"input-text\">\r\n <textarea rows=\"10\" matInput [formControl]=\"control\" tpSurveyFocusAndSelect></textarea>\r\n </mat-form-field>\r\n }\r\n</div>\r\n", styles: [":host{width:100%}.container-main{display:flex;width:100%;justify-content:center;align-items:center;flex-flow:column;gap:2em;padding:0 2em;box-sizing:border-box}.input-text{width:100%}\n"] }]
|
|
976
982
|
}] });
|
|
977
983
|
|
|
978
984
|
class AsFormArrayPipe {
|
|
@@ -1298,7 +1304,7 @@ class ContainerAnswerComponent {
|
|
|
1298
1304
|
break;
|
|
1299
1305
|
}
|
|
1300
1306
|
case QuestionsType.eqMS: {
|
|
1301
|
-
this.answerForm.controls.answer.addValidators(answerMSValidator(this.visibleAlternativeList()
|
|
1307
|
+
this.answerForm.controls.answer.addValidators(answerMSValidator(this.visibleAlternativeList(), this.question().AlternativeMinAnswersCount, this.question().AlternativeMaxAnswersCount));
|
|
1302
1308
|
break;
|
|
1303
1309
|
}
|
|
1304
1310
|
case QuestionsType.eqOD: {
|
|
@@ -1813,8 +1819,8 @@ class TpSurveyCoreService {
|
|
|
1813
1819
|
if (!currentQuestion) {
|
|
1814
1820
|
return;
|
|
1815
1821
|
}
|
|
1816
|
-
//если ответ на текущий вопрос не
|
|
1817
|
-
if (!this._interview.questionIsComplete(currentQuestion.QuestionGuid)) {
|
|
1822
|
+
//если ответ на текущий вопрос не закончен И опция пропуска вопроса не активна, выходим
|
|
1823
|
+
if (!this._interview.questionIsComplete(currentQuestion.QuestionGuid) && !currentQuestion.CanSkip) {
|
|
1818
1824
|
return;
|
|
1819
1825
|
}
|
|
1820
1826
|
//если указан PostScript, выполним его
|
|
@@ -2475,7 +2481,9 @@ class SurveyPlayComponent {
|
|
|
2475
2481
|
* кнопка далее нужно проверять при показе вопроса и при изменении ответа. При показе она может быть доступна сразу(например info).
|
|
2476
2482
|
* Кнопка доступна если ответ корректно заполнен(questionIsComplete) и это не eqEND вопрос
|
|
2477
2483
|
* */
|
|
2478
|
-
this.nextButtonAvailable = toSignal(merge(this.#core.on(SurveyEvents.seQuestionAnswersChange).pipe(map(data => data.question)), this.#core.on(SurveyEvents.seQuestionShow).pipe(map(data => data))).pipe(
|
|
2484
|
+
this.nextButtonAvailable = toSignal(merge(this.#core.on(SurveyEvents.seQuestionAnswersChange).pipe(map(data => data.question)), this.#core.on(SurveyEvents.seQuestionShow).pipe(map(data => data))).pipe(
|
|
2485
|
+
//вопрос должен быть не eqEND и не eqLANG(для них кнопки далее быть не должно) + вопрос должен быть заполнен или его можно пропустить(указано в настройках)
|
|
2486
|
+
map(question => !([QuestionsType.eqEND, QuestionsType.eqLANG].includes(question.QuestionType)) && (this.#core.questionIsComplete(question.QuestionGuid) || question.CanSkip)), delay(1)), { initialValue: false });
|
|
2479
2487
|
//кнопку Назад можно показывать если в настройках указали ShowBtnBack и это не eqEND вопрос
|
|
2480
2488
|
this.backButtonAvailable = toSignal(this.#core.on(SurveyEvents.seQuestionShow).pipe(filter(question => !!question), map((question) => question.QuestionNum > 1 && question.ShowBtnBack && question.QuestionType !== QuestionsType.eqEND && question.QuestionType !== QuestionsType.eqLANG), delay(1)));
|
|
2481
2489
|
this.#core.on(SurveyEvents.seSurveyEnd).pipe(takeUntilDestroyed(this.#destroyRef)).subscribe({
|