forked from tykayn/funky-framadate-front
floating hint about form errors
This commit is contained in:
parent
f66603d187
commit
7ef4e4d4a4
@ -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');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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,9 +93,11 @@
|
||||
<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>
|
||||
<div class="proposed-answers">
|
||||
<h3 class="title is-3">
|
||||
<i class="fa fa-check-square"></i>
|
||||
Réponses proposées
|
||||
@ -108,13 +110,15 @@
|
||||
<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">
|
||||
|
@ -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">
|
||||
|
@ -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>
|
||||
|
@ -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)]],
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -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">
|
||||
|
@ -0,0 +1,9 @@
|
||||
.fixed-hint {
|
||||
position: fixed;
|
||||
left: 9em;
|
||||
bottom: 3em;
|
||||
padding: 1em;
|
||||
border-radius: 1em;
|
||||
color: white;
|
||||
border: solid 2px white;
|
||||
}
|
@ -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 = [];
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -27,3 +27,7 @@ h3 {
|
||||
h4 {
|
||||
@extend .is-4;
|
||||
}
|
||||
|
||||
.nobold {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user