Skip to content

Commit

Permalink
Added modal component for predefined form options. (#300)
Browse files Browse the repository at this point in the history
  • Loading branch information
VladCuciureanu authored Nov 22, 2020
1 parent d4ffb24 commit 86788bb
Show file tree
Hide file tree
Showing 11 changed files with 260 additions and 61 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"start": "ng serve --proxyConfig proxy.conf.json",
"start-qa": "ng serve --configuration=qa",
"start-prod": "ng serve --configuration=prod",
"start-local": "ng serve --configuration=local",
"build": "ng build --prod",
"build-token": "npm run build -- --configuration=token",
"lint": "tslint \"src/**/*.ts\""
Expand Down
114 changes: 58 additions & 56 deletions src/app/components/components.module.ts
Original file line number Diff line number Diff line change
@@ -1,72 +1,74 @@
import { SharedModule } from '../shared/shared.module';
import { NgModule } from '@angular/core';
import { AnswerExtraQuestionsComponent } from './answer/answer-extra-questions/answer-extra-questions.component';
import { LoginComponent } from './login/login.component';
import { StatisticsValueComponent } from './statistics/statistics-value/statistics-value.component';
import { AnswerNoteComponent } from './answer/answer-note/answer-note.component';
import { StatisticsDetailsComponent } from './statistics/statistics-details/statistics-details.component';
import { CategoricalQuestionComponent } from './answer/categorical-question/categorical-question.component';
import { StatisticsCardComponent } from './statistics/statistics-card/statistics-card.component';
import { StatisticsComponent } from './statistics/statistics.component';
import { AnswerFormListComponent } from './answer/answer-form-list/answer-form-list.component';
import { AnswerDetailsComponent } from './answer/answer-details/answer-details.component';
import { AnswerComponent } from './answer/answer.component';
import { ObserversComponent } from './observers/observers.component';
import { AnswerListComponent } from './answer/answers-list/answer-list.component';
import { HeaderComponent } from './header/header.component';
import { ObserverCardComponent } from './observers/observer-card/observer-card.component';
import { OberverRowComponent } from './observers/oberver-row/oberver-row.component';
import { ObserverProfileComponent } from './observers/observer-profile/observer-profile.component';
import { NotificationsComponent } from './notifications/notifications.component';
import { NgMultiSelectDropDownModule } from 'ng-multiselect-dropdown';
import {SharedModule} from '../shared/shared.module';
import {NgModule} from '@angular/core';
import {AnswerExtraQuestionsComponent} from './answer/answer-extra-questions/answer-extra-questions.component';
import {LoginComponent} from './login/login.component';
import {StatisticsValueComponent} from './statistics/statistics-value/statistics-value.component';
import {AnswerNoteComponent} from './answer/answer-note/answer-note.component';
import {StatisticsDetailsComponent} from './statistics/statistics-details/statistics-details.component';
import {CategoricalQuestionComponent} from './answer/categorical-question/categorical-question.component';
import {StatisticsCardComponent} from './statistics/statistics-card/statistics-card.component';
import {StatisticsComponent} from './statistics/statistics.component';
import {AnswerFormListComponent} from './answer/answer-form-list/answer-form-list.component';
import {AnswerDetailsComponent} from './answer/answer-details/answer-details.component';
import {AnswerComponent} from './answer/answer.component';
import {ObserversComponent} from './observers/observers.component';
import {AnswerListComponent} from './answer/answers-list/answer-list.component';
import {HeaderComponent} from './header/header.component';
import {ObserverCardComponent} from './observers/observer-card/observer-card.component';
import {OberverRowComponent} from './observers/oberver-row/oberver-row.component';
import {ObserverProfileComponent} from './observers/observer-profile/observer-profile.component';
import {NotificationsComponent} from './notifications/notifications.component';
import {NgMultiSelectDropDownModule} from 'ng-multiselect-dropdown';
import {FormCreateComponent} from './forms/form-create/form-create.component';
import {SectionComponent} from './forms/section/section.component';
import {QuestionComponent} from './forms/question/question.component';
import {PredefinedOptionsModalComponent} from './forms/predefined-options-modal/predefined-options-modal.component';
import {OptionComponent} from './forms/option/option.component';
import {FormsComponent} from './forms/forms.component';
import {DragDropModule} from '@angular/cdk/drag-drop';

import { TableModule } from '../table/table.module'
import { ObserverImportComponent } from './observers/observer-import/observer-import.component';
import {TableModule} from '../table/table.module'
import {ObserverImportComponent} from './observers/observer-import/observer-import.component';

export let components = [
AnswerComponent,
AnswerListComponent,
AnswerDetailsComponent,
AnswerFormListComponent,
AnswerNoteComponent,
CategoricalQuestionComponent,
AnswerExtraQuestionsComponent,
ObserversComponent,
ObserverCardComponent,
OberverRowComponent,
ObserverProfileComponent,
FormsComponent,
FormCreateComponent,
SectionComponent,
QuestionComponent,
OptionComponent,
HeaderComponent,
StatisticsComponent,
StatisticsCardComponent,
StatisticsDetailsComponent,
StatisticsValueComponent,
NotificationsComponent,
LoginComponent,
ObserverImportComponent,
AnswerComponent,
AnswerListComponent,
AnswerDetailsComponent,
AnswerFormListComponent,
AnswerNoteComponent,
CategoricalQuestionComponent,
AnswerExtraQuestionsComponent,
ObserversComponent,
ObserverCardComponent,
OberverRowComponent,
ObserverProfileComponent,
FormsComponent,
FormCreateComponent,
SectionComponent,
QuestionComponent,
PredefinedOptionsModalComponent,
OptionComponent,
HeaderComponent,
StatisticsComponent,
StatisticsCardComponent,
StatisticsDetailsComponent,
StatisticsValueComponent,
NotificationsComponent,
LoginComponent,
ObserverImportComponent,
];

@NgModule({
declarations: components,
exports: components,
imports: [
SharedModule,
NgMultiSelectDropDownModule.forRoot(),
DragDropModule,
TableModule,
]
declarations: components,
exports: components,
imports: [
SharedModule,
NgMultiSelectDropDownModule.forRoot(),
DragDropModule,
TableModule,
]
})
export class ComponentsModule {
export class ComponentsModule {

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<div class="modal-header">
<h6 class="modal-title">{{'PREDEFINED_OPTIONS_MODAL.TITLE' | translate}}</h6>
</div>
<div class="modal-body">
<p>{{'PREDEFINED_OPTIONS_MODAL.NOTE' | translate}}</p>
<div *ngFor="let category of data">
{{ category.label | translate }}
<div *ngFor="let option of category.options" class="node-children">
<input type="checkbox" [ngModel]="option.check"
(ngModelChange)="check(option,$event);"/> {{ option.label | translate }}
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary" (click)="modal.dismiss()">{{'CANCEL' | translate}}</button>
<button type="button" class="btn btn-warning" (click)="modal.close(getChecked())">{{'ADD' | translate}}</button>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.node-children {
margin: 1.5px 1.5px 1.5px 15px;
padding-left: 10px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import {Component, OnInit} from '@angular/core';
import {NgbActiveModal} from '@ng-bootstrap/ng-bootstrap';
import predefinedOptions from '../../../../assets/configs/predefined-options.json';

interface Category {
label: string;
options: Option[];
}

interface Option {
label: string;
check?: boolean;
}

@Component({
selector: 'app-predefined-options-modal',
templateUrl: './predefined-options-modal.component.html',
styleUrls: ['./predefined-options-modal.component.scss']
})
export class PredefinedOptionsModalComponent implements OnInit {
data: Category[];
private readonly checkboxPersistentData: any;

constructor(public modal: NgbActiveModal) {
if (!localStorage.getItem('selectedPredefinedOptions')) {
localStorage.setItem('selectedPredefinedOptions', '{}');
}
try {
this.checkboxPersistentData = JSON.parse(localStorage.getItem('selectedPredefinedOptions'));
} catch {
localStorage.setItem('selectedPredefinedOptions', '{}');
this.checkboxPersistentData = {};
}

this.data = predefinedOptions;

this.data.forEach(category => {
category.options.forEach(option => {
if (option.label in this.checkboxPersistentData)
this.check(option, this.checkboxPersistentData[option.label] === 'true')
})
})
}

check(option: Option, value: boolean) {
option.check = value;
this.checkboxPersistentData[option.label] = value ? 'true' : 'false';
localStorage.setItem('selectedPredefinedOptions', JSON.stringify(this.checkboxPersistentData));
}

getChecked() {
const result = []
this.data.forEach(category => {
category.options.forEach(option => {
if (option.check)
result.push(option.label)
})
})
return result;
}

ngOnInit() {
}
}


7 changes: 4 additions & 3 deletions src/app/components/forms/question/question.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@
</div>
</div>
</div>

<div class="col add-option-button" (click)="addOption()">+ {{'OPTION_ADD' | translate}}</div>

<div class="col">
<div class="add-option-button" style="display: inline; padding-right: 30px;" (click)="addOption()">+ {{'OPTION_ADD' | translate}}</div>
<div class="add-option-button" style="display: inline" (click)="choosePredefinedOption()">+ {{'PREDEFINED_OPTIONS_MODAL.ADD' | translate}}</div>
</div>
</div>
</div>
23 changes: 22 additions & 1 deletion src/app/components/forms/question/question.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {initOptionFormGroup} from '../form-groups-builder';
import {moveItemInFormArray} from '../../utils';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { ConfirmationModalComponent } from 'src/app/shared/confirmation-modal/confirmation-modal.component';
import {PredefinedOptionsModalComponent} from '../predefined-options-modal/predefined-options-modal.component';
import {TranslateService} from '@ngx-translate/core';

@Component({
selector: 'app-question',
Expand All @@ -22,7 +24,7 @@ export class QuestionComponent implements OnInit {

questionTypes: QuestionType[];

constructor(private formBuilder: FormBuilder, private _modalService: NgbModal) {}
constructor(private formBuilder: FormBuilder, private _modalService: NgbModal, private translate: TranslateService) {}


ngOnInit() {
Expand All @@ -41,6 +43,25 @@ export class QuestionComponent implements OnInit {
this.optionsArray.push(initOptionFormGroup(this.formBuilder));
}

addOptionWithText(givenText: string) {
const formGroup = initOptionFormGroup(this.formBuilder);
formGroup.patchValue({text: givenText});
this.optionsArray.push(formGroup);
}

choosePredefinedOption() {
const modalRef = this._modalService.open(PredefinedOptionsModalComponent);
modalRef.result.then(resultList => {
resultList.forEach(selectedOption => {
const translatedSelectedOption = this.translate.instant(selectedOption);
if (!this.optionFormGroupsArray.some(item => item.get('text').value === translatedSelectedOption))
this.addOptionWithText(translatedSelectedOption);
})
})
.catch(() => {
});
}

toggleOptions() {
this.hideOptions = !this.hideOptions;
}
Expand Down
36 changes: 36 additions & 0 deletions src/assets/configs/predefined-options.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
[
{
"label": "PREDEFINED_OPTIONS.CONFIRMATION.LABEL",
"options": [
{
"label": "PREDEFINED_OPTIONS.CONFIRMATION.YES"
},
{
"label": "PREDEFINED_OPTIONS.CONFIRMATION.NO"
},
{
"label": "PREDEFINED_OPTIONS.CONFIRMATION.DONT_KNOW"
}
]
},
{
"label": "PREDEFINED_OPTIONS.RATING.LABEL",
"options": [
{
"label": "PREDEFINED_OPTIONS.RATING.1"
},
{
"label": "PREDEFINED_OPTIONS.RATING.2"
},
{
"label": "PREDEFINED_OPTIONS.RATING.3"
},
{
"label": "PREDEFINED_OPTIONS.RATING.4"
},
{
"label": "PREDEFINED_OPTIONS.RATING.5"
}
]
}
]
24 changes: 24 additions & 0 deletions src/assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,29 @@

"OPTION_ADD": "Add option",

"PREDEFINED_OPTIONS": {
"CONFIRMATION": {
"LABEL": "Confirmations",
"YES": "Yes",
"NO": "No",
"DONT_KNOW": "Don't know"
},
"RATING": {
"LABEL": "Ratings",
"1": "1 - Very Bad",
"2": "2 - Bad",
"3": "3 - Mediocre",
"4": "4 - Good",
"5": "5 - Very Good"
}
},

"PREDEFINED_OPTIONS_MODAL": {
"ADD": "Choose predefined options",
"TITLE": "Choose from predefined options",
"NOTE": "Note: Your selection will be remembered"
},

"NOTHING_SELECTED": "Nothing selected.",
"SHOW": "Show",
"HIDE": "Hide",
Expand Down Expand Up @@ -113,6 +136,7 @@
"LAST_LOGIN": "Last login",

"//": "COMMON_STUFF",
"ADD": "Add",
"EDIT": "Edit",
"DELETE": "Delete",
"SEND_NOTIF": "Send Notification",
Expand Down
25 changes: 25 additions & 0 deletions src/assets/i18n/ro.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,30 @@

"OPTION_ADD": "Adaugă o opţiune",

"PREDEFINED_OPTIONS": {
"CONFIRMATION": {
"LABEL": "Confirmari",
"YES": "Da",
"NO": "Nu",
"DONT_KNOW": "Nu stiu"
},
"RATING": {
"LABEL": "Calificative",
"1": "1 - Foarte slab",
"2": "2 - Slab",
"3": "3 - Mediu",
"4": "4 - Bine",
"5": "5 - Foarte bine"
}
},

"PREDEFINED_OPTIONS_MODAL": {
"ADD": "Alege optiuni prestabilite",
"TITLE": "Alege din optiunile prestabilite",
"NOTE": "Observatie: Optiunile selectate vor fi salvate"
},


"NOTHING_SELECTED": "Nu ati selectat nimic",
"SHOW": "Vezi",
"HIDE": "Ascunde",
Expand Down Expand Up @@ -97,6 +121,7 @@


"//": "COMMON_STUFF",
"ADD": "Adaugă",
"EDIT": "Editaţi",
"DELETE": "Ștergeţi",
"SEND_NOTIF": "Trimiteţi Notificare",
Expand Down
Loading

1 comment on commit 86788bb

@vercel
Copy link

@vercel vercel bot commented on 86788bb Nov 22, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.