floating hint about form errors

This commit is contained in:
Tykayn 2021-05-18 10:47:16 +02:00 committed by tykayn
parent f66603d187
commit 7ef4e4d4a4
14 changed files with 180 additions and 198 deletions

View File

@ -1,8 +1,9 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Component, Inject, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs';
import { Poll } from '../../core/models/poll.model';
import { DOCUMENT } from '@angular/common';
@Component({
selector: 'app-administration',
@ -13,7 +14,7 @@ export class AdministrationComponent implements OnInit, OnDestroy {
public poll: Poll;
private routeSubscription: Subscription;
constructor(private route: ActivatedRoute) {}
constructor(private route: ActivatedRoute, @Inject(DOCUMENT) private document: any) {}
ngOnInit(): void {
this.routeSubscription = this.route.data.subscribe((data: { poll: Poll }) => {
@ -21,6 +22,15 @@ export class AdministrationComponent implements OnInit, OnDestroy {
if (data.poll) {
this.poll = data.poll;
}
// focus on first field of the creation form
const firstField = this.document.querySelector('app-admin-form select');
if (firstField) {
console.log('focus on ', firstField);
firstField.focus();
} else {
console.log('no first field of form');
}
});
}

View File

@ -74,7 +74,7 @@
<mat-checkbox class="is-not-flex" formControlName="isProtectedByPassword">
Le sondage sera protégé par un mot de passe
</mat-checkbox>
<br />
<input
*ngIf="form.value.isProtectedByPassword"
#password
@ -93,28 +93,32 @@
<mat-checkbox class="is-not-flex" formControlName="isOwnerNotifiedByEmailOnNewVote">
Vous recevrez un mail à chaque nouvelle participation
</mat-checkbox>
<br />
<mat-checkbox class="is-not-flex" formControlName="isOwnerNotifiedByEmailOnNewComment">
Vous recevrez un mail à chaque nouveau commentaire
</mat-checkbox>
<h3 class="title is-3">
<i class="fa fa-check-square"></i>
Réponses proposées
</h3>
<div class="proposed-answers">
<h3 class="title is-3">
<i class="fa fa-check-square"></i>
Réponses proposées
</h3>
<img class="image is-24x24 pull-right" src="assets/img/icon_voter_YES.svg" />
<img class="image is-24x24 pull-right" src="assets/img/icon_voter_MAYBE.svg" />
<img class="image is-24x24 pull-right" src="assets/img/icon_voter_NO.svg" />
<mat-checkbox class="is-not-flex" formControlName="isYesAnswerAvailable">
La réponse « oui » sera disponible
</mat-checkbox>
<mat-checkbox class="is-not-flex" formControlName="isMaybeAnswerAvailable">
La réponse « peut-être » sera disponible
</mat-checkbox>
<mat-checkbox class="is-not-flex" formControlName="isNoAnswerAvailable">
La réponse « non » sera disponible
</mat-checkbox>
<img class="image is-24x24 pull-right" src="assets/img/icon_voter_YES.svg" />
<img class="image is-24x24 pull-right" src="assets/img/icon_voter_MAYBE.svg" />
<img class="image is-24x24 pull-right" src="assets/img/icon_voter_NO.svg" />
<mat-checkbox class="is-not-flex" formControlName="isYesAnswerAvailable">
La réponse « oui » sera disponible
</mat-checkbox>
<br />
<mat-checkbox class="is-not-flex" formControlName="isMaybeAnswerAvailable">
La réponse « peut-être » sera disponible
</mat-checkbox>
<br />
<mat-checkbox class="is-not-flex" formControlName="isNoAnswerAvailable">
La réponse « non » sera disponible
</mat-checkbox>
</div>
<h3 class="title is-3">
<i class="fa fa-user-secret"></i>
Restrictions visiteurs
@ -122,6 +126,7 @@
<mat-checkbox class="is-not-flex" formControlName="allowComments">
Autoriser les commentaires
</mat-checkbox>
<br />
<mat-checkbox class="is-not-flex" formControlName="hasMaxCountOfAnswers">
Nombre de réponses limitées à ce nombre
</mat-checkbox>
@ -145,7 +150,7 @@
<app-wip-todo></app-wip-todo>
<div>
<mat-checkbox class="is-not-flex" formControlName="isProtectedByPassword">
<mat-checkbox class="is-not-flex" formControlName="useVoterUniqueLink">
Spécifier un lien unique de vote à des participants définis
</mat-checkbox>
<p>
@ -153,6 +158,13 @@
avec une clé permettant de voter pour n'importe qui ayant le lien. Nécessite: évolution de la BDD et de
l'API
</p>
<textarea
name="voterEmailList"
id="voterEmailList"
cols="30"
rows="10"
formControlName="voterEmailList"
></textarea>
</div>
<mat-checkbox class="is-not-flex" formControlName="allowNewDateTime">

View File

@ -25,9 +25,9 @@
>
<i class="fa fa-close"></i>
</button>
<mat-error class="hint deletable-field-hint" *ngIf="form.controls.title.invalid">{{
getErrorMessage(form.controls.title)
}}</mat-error>
<mat-error class="hint deletable-field-hint" *ngIf="form.controls.title.invalid">
{{ getErrorMessage(form.controls.title) }}</mat-error
>
<br />
<label for="creatorEmail">

View File

@ -61,22 +61,13 @@
</main>
<app-picker [form]="form" *ngIf="displayDatePicker"></app-picker>
<app-errors-list [form]="form"></app-errors-list>
<p>
<i>
{{ 'choices.helper' | translate }}
</i>
</p>
{{ 'choices.answer_preset_1' | translate }}
{{ 'choices.add' | translate }}
{{ 'choices.continue' | translate }}
<button
[disabled]="!form.valid && form.touched"
class="btn is-success is-fixed-bottom"
(click)="createPoll()"
>
<i class="fa fa-save"></i>
Enregistrer le sondage (vérifier la validité)
Enregistrer le sondage
</button>
<button class="btn is-success is-fixed-bottom" (click)="createPoll()" *ngIf="!environment.production">
<i class="fa fa-save"></i>
@ -97,15 +88,6 @@
>
</footer>
<hr />
<div class="validation">
<div class="has-background-danger" *ngIf="!form.valid && form.touched">
le formulaire est invalide
<pre>
{{ form.errors | json }}
</pre
>
</div>
</div>
</form>
</div>
</div>

View File

@ -22,7 +22,7 @@ export class FormComponent implements OnInit {
public form: FormGroup;
public displayDatePicker = false;
public advancedDisplayEnabled = false;
public advancedDisplayEnabled = true;
public show_debug_data = false;
public currentStep = 'base';
public steps = ['base', 'choices', 'advanced'];
@ -50,35 +50,13 @@ export class FormComponent implements OnInit {
initFormDefault(showDemoValues = environment.autofill): void {
const creationDate = new Date();
// choices of date are managed outside of this form
this.form = this.fb.group({
title: ['', [Validators.required, Validators.minLength(5)]],
creatorPseudo: ['', [Validators.required]],
creatorEmail: ['', [Validators.required]],
custom_url: [this.pollUtilitiesService.makeUuid(), [Validators.required]],
description: ['', [Validators.required]],
// choices: this.fb.array([
// this.fb.group({
// label: ['', [Validators.required]],
// imageUrl: ['', [Validators.required]],
// }),
// ]),
// dateChoices: this.fb.array([
// this.fb.group({
// label: ['', [Validators.required]],
// // if we have enabled detailed time choices per date choice, we have to make a time property for each date choice
// timeChoices: this.fb.array([
// this.fb.group({
// label: ['', [Validators.required]],
// }),
// ]),
// }),
// ]),
// // these time choice are meant to be the same for each day
// timeChoices: this.fb.array([
// this.fb.group({
// label: ['', [Validators.required]],
// }),
// ]),
kind: ['', [Validators.required]],
areResultsPublic: [true, [Validators.required]],
whoCanChangeAnswers: ['everybody', [Validators.required]],
@ -91,10 +69,12 @@ export class FormComponent implements OnInit {
isNoAnswerAvailable: [false, [Validators.required]],
isAboutDate: [true, [Validators.required]],
isZeroKnoledge: [false, [Validators.required]],
useVoterUniqueLink: [false, [Validators.required]],
expiresDaysDelay: [60, [Validators.required, Validators.min(1)]],
maxCountOfAnswers: [150, [Validators.required, Validators.min(1)]],
allowComments: [true, [Validators.required]],
password: ['', []],
voterEmailList: ['', []],
dateCreated: [creationDate, [Validators.required]],
hasSeveralHours: [false, [Validators.required]],
hasMaxCountOfAnswers: [true, [Validators.required, Validators.min(1)]],

View File

@ -52,10 +52,6 @@ export class ConsultationComponent implements OnInit, OnDestroy {
if (newpoll) {
this.isArchived = new Date(newpoll.expiracy_date) < new Date();
this.poll.is_archived = this.isArchived;
if (!environment.production) {
// this.addVoteStack();
}
}
});

View File

@ -9,6 +9,10 @@
<strong class="marged has-background-warning total-errors" *ngIf="form && totalErrors">
{{ totalErrors }} erreurs de validation
</strong>
<strong class="marged has-background-warning total-errors fixed-hint" *ngIf="form && totalErrors">
{{ totalErrors }}
<i class="fa fa-warning"></i>
</strong>
<ul>
<li *ngFor="let m of messages">

View File

@ -0,0 +1,9 @@
.fixed-hint {
position: fixed;
left: 9em;
bottom: 3em;
padding: 1em;
border-radius: 1em;
color: white;
border: solid 2px white;
}

View File

@ -19,7 +19,7 @@ export class ErrorsListComponent implements OnInit {
}
getFormValidationErrors(): void {
// console.log('%c ==>> Validation Errors: ', 'color: red; font-weight: bold; font-size:25px;');
console.log('%c ==>> Validation Errors: ', 'color: red; font-weight: bold; font-size:22px;');
let totalErrors = 0;
this.messages = [];

View File

@ -141,6 +141,10 @@
"selectors": {
"lang": "Select the lang"
},
"validation" : {
"You must enter a value": "You must enter a EEEE"
},
"You must enter a value": "You must enter a valueeeeeeee",
"SENTENCES": {
"create-a-poll": "Create a poll",
"define-dates-or-subjects-to-choose-from": "Define dates or subjects to choose from",

View File

@ -144,6 +144,10 @@
"selectors": {
"lang": "Sélectionner la langue"
},
"validation" : {
"You must enter a value": "You must enter a EEEE"
},
"You must enter a value": "You must enter a valueeeeeeee",
"SENTENCES": {
"create-a-poll": "Créez un sondage",
"define-dates-or-subjects-to-choose-from": "Déterminez les dates ou les sujets à choisir",

View File

@ -1,91 +0,0 @@
input,
select,
textarea {
@extend .clickable;
margin-bottom: 0.25rem;
border-bottom: 2px solid $primary_color;
padding: 0.5rem;
&:active,
&:focus,
&:hover {
color: $primary_color;
}
&.ng-invalid {
border: $warning 3px solid !important;
}
}
input[required] {
&:after {
content: '*';
color: red;
}
}
select,
option {
-webkit-appearance: none;
-moz-appearance: none;
border-radius: 0;
background-color: transparent;
//background-image: url('/assets/img/fleche_bas.svg');
padding-right: 2.5rem;
background-repeat: no-repeat;
background-size: 9px 8px;
background-position: right 1rem center;
background-clip: border-box;
min-width: 10rem;
margin-bottom: 0.25rem;
border-bottom: 2px solid $primary_color !important;
}
select {
@extend .select, .input;
}
#multi_hours select {
min-width: 300px !important;
}
input {
@extend .input, .text-ellipsis;
}
label {
margin-top: 0.5rem;
}
textarea {
width: 100%;
max-width: 100%;
min-height: 213px;
padding: 0.5em 1em;
margin-bottom: 1em;
border-left: 3px solid $primary_color;
}
.comment {
border-left: 6px solid $primary_color;
margin-top: 25px;
margin-bottom: 25px;
flex-wrap: wrap;
padding-left: 17px;
}
.cname {
font-weight: bold;
}
.deletable-field-hint {
margin-right: 2.8em;
margin-top: -0.7em;
-moz-border-radius-bottomright: 1em;
}
.mat-error {
display: block;
background: $warning;
padding: 1em;
}

View File

@ -1,34 +1,9 @@
@charset "UTF-8";
label {
margin-top: 1em;
margin-top: 0.25em;
line-height: 2.5em;
}
.ui-inputswitch {
margin-left: 1ch;
margin-right: 1ch;
}
.input-lg {
display: block;
width: 100%;
}
input {
margin-bottom: 1em;
+ button,
+ .mat-icon-button {
margin-bottom: 1em;
}
&[type='date']::after {
content: 'au format JJ/MM/AAAA';
display: inline-block;
position: relative;
}
}
input,
select,
textarea {
@ -36,26 +11,50 @@ textarea {
padding: 1rem;
border: 1px solid $secondary_color;
border-bottom: 3px solid $primary_color;
width: calc(100% - 45px) !important;
max-width: 40em !important;
width: calc(100% -45px);
margin-right: 2px;
margin-bottom: 1em;
+ button,
+ .mat-icon-button {
margin-bottom: 1em;
}
}
.next {
max-width: 200px;
input,
select,
textarea {
@extend .clickable;
margin-bottom: 0.25rem;
border-bottom: 2px solid $primary_color;
padding: 0.5rem;
&:active,
&:focus,
&:hover {
color: $primary_color;
}
&.ng-invalid {
border: $warning 3px solid !important;
}
&[required] {
&:after {
content: '*';
color: red;
}
}
}
li {
list-style-type: none;
}
.next {
max-width: 200px;
margin-bottom: 50px;
}
.nobold {
font-weight: normal;
}
.btn-block {
display: block;
width: 100%;
@ -72,3 +71,72 @@ button[type='submit'] {
background: $warning;
color: $white;
}
select,
option {
-webkit-appearance: none;
-moz-appearance: none;
border-radius: 0;
background-color: transparent;
background-image: url('assets/img/fleche_bas.svg') !important;
padding-right: 2.5rem;
background-repeat: no-repeat;
background-size: 9px 8px;
background-position: right 1rem center;
background-clip: border-box;
min-width: 10rem;
margin-bottom: 0.25rem;
border-bottom: 2px solid $primary_color !important;
}
select {
@extend .select, .input;
}
#multi_hours select {
min-width: 300px !important;
}
input {
@extend .input, .text-ellipsis;
}
label {
margin-top: 0.5rem;
}
textarea {
width: 100%;
max-width: 100%;
min-height: 213px;
padding: 0.5em 1em;
margin-bottom: 1em;
border-left: 3px solid $primary_color;
}
.comment {
border-left: 6px solid $primary_color;
margin-top: 25px;
margin-bottom: 25px;
flex-wrap: wrap;
padding-left: 17px;
}
.cname {
font-weight: bold;
}
.deletable-field-hint {
margin-right: 2.8em;
margin-top: -0.7em;
-moz-border-radius-bottomright: 1em;
}
.mat-error {
display: block;
background: $warning;
padding: 1em;
}
mat-checkbox {
display: block;
}

View File

@ -27,3 +27,7 @@ h3 {
h4 {
@extend .is-4;
}
.nobold {
font-weight: normal;
}