diff --git a/src/app/shared/cancel-dialog/cancel-dialog.component.html b/src/app/shared/cancel-dialog/cancel-dialog.component.html
new file mode 100644
index 000000000..a98c6c5e3
--- /dev/null
+++ b/src/app/shared/cancel-dialog/cancel-dialog.component.html
@@ -0,0 +1,8 @@
+
Cancel
+
+
Are you sure you want to leave this page and lose all inputted data?
+
+
+
+
+
diff --git a/src/app/shared/cancel-dialog/cancel-dialog.component.scss b/src/app/shared/cancel-dialog/cancel-dialog.component.scss
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/app/shared/cancel-dialog/cancel-dialog.component.spec.ts b/src/app/shared/cancel-dialog/cancel-dialog.component.spec.ts
new file mode 100644
index 000000000..94decaa50
--- /dev/null
+++ b/src/app/shared/cancel-dialog/cancel-dialog.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { CancelDialogComponent } from './cancel-dialog.component';
+
+describe('CancelDialogComponent', () => {
+ let component: CancelDialogComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ CancelDialogComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(CancelDialogComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/shared/cancel-dialog/cancel-dialog.component.ts b/src/app/shared/cancel-dialog/cancel-dialog.component.ts
new file mode 100644
index 000000000..937071198
--- /dev/null
+++ b/src/app/shared/cancel-dialog/cancel-dialog.component.ts
@@ -0,0 +1,23 @@
+/** Angular Imports */
+import { Component, OnInit, Inject } from '@angular/core';
+import { MatDialogRef } from '@angular/material';
+
+/**
+ * Cancel dialog component.
+ */
+@Component({
+ selector: 'mifosx-cancel-dialog',
+ templateUrl: './cancel-dialog.component.html',
+ styleUrls: ['./cancel-dialog.component.scss']
+})
+export class CancelDialogComponent implements OnInit {
+
+ /**
+ * @param {MatDialogRef} dialogRef Component reference to dialog.
+ */
+ constructor(public dialogRef: MatDialogRef) { }
+
+ ngOnInit() {
+ }
+
+}
diff --git a/src/app/shared/material.module.ts b/src/app/shared/material.module.ts
index 25b7fd88d..dc4d9d482 100644
--- a/src/app/shared/material.module.ts
+++ b/src/app/shared/material.module.ts
@@ -1,6 +1,7 @@
/** Angular Imports */
import { NgModule } from '@angular/core';
import { LayoutModule } from '@angular/cdk/layout';
+import { DragDropModule } from '@angular/cdk/drag-drop';
import { STEPPER_GLOBAL_OPTIONS } from '@angular/cdk/stepper';
import { FlexLayoutModule } from '@angular/flex-layout';
import {
@@ -48,6 +49,7 @@ import {
*/
@NgModule({
exports: [
+ DragDropModule,
FlexLayoutModule,
LayoutModule,
MatAutocompleteModule,
diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts
index 2e23e0cbb..fa97cf891 100644
--- a/src/app/shared/shared.module.ts
+++ b/src/app/shared/shared.module.ts
@@ -7,6 +7,7 @@ import { ReactiveFormsModule, FormsModule } from '@angular/forms';
import { FormfieldComponent } from './form-dialog/formfield/formfield.component';
import { FormDialogComponent } from './form-dialog/form-dialog.component';
import { DeleteDialogComponent } from './delete-dialog/delete-dialog.component';
+import { CancelDialogComponent } from './cancel-dialog/cancel-dialog.component';
import { FileUploadComponent } from './file-upload/file-upload.component';
import { FooterComponent } from './footer/footer.component';
import { LanguageSelectorComponent } from './language-selector/language-selector.component';
@@ -37,6 +38,7 @@ import { MaterialModule } from './material.module';
FormfieldComponent,
FormDialogComponent,
DeleteDialogComponent,
+ CancelDialogComponent,
FileUploadComponent,
FooterComponent,
LanguageSelectorComponent,
@@ -65,7 +67,8 @@ import { MaterialModule } from './material.module';
EnableDialogComponent,
DisableDialogComponent,
ConfirmationDialogComponent,
- KeyboardShortcutsDialogComponent
+ KeyboardShortcutsDialogComponent,
+ CancelDialogComponent
]
})
export class SharedModule { }
diff --git a/src/app/system/manage-surveys/create-survey/create-survey.component.html b/src/app/system/manage-surveys/create-survey/create-survey.component.html
new file mode 100644
index 000000000..031aa7a2a
--- /dev/null
+++ b/src/app/system/manage-surveys/create-survey/create-survey.component.html
@@ -0,0 +1,169 @@
+
diff --git a/src/app/system/manage-surveys/create-survey/create-survey.component.scss b/src/app/system/manage-surveys/create-survey/create-survey.component.scss
new file mode 100644
index 000000000..6bf9c100a
--- /dev/null
+++ b/src/app/system/manage-surveys/create-survey/create-survey.component.scss
@@ -0,0 +1,21 @@
+.delete-wrapper {
+ padding: 17.5px 0 0 0;
+}
+
+h2 {
+ font-weight: 500;
+ margin: 0;
+}
+
+h4 {
+ font-weight: 500;
+ margin: 0;
+}
+
+.mat-card .mat-divider-horizontal.mat-divider-inset {
+ margin: 1em 0 2em 0;
+}
+
+.cdk-drag-placeholder {
+ opacity: 0;
+}
diff --git a/src/app/system/manage-surveys/create-survey/create-survey.component.spec.ts b/src/app/system/manage-surveys/create-survey/create-survey.component.spec.ts
new file mode 100644
index 000000000..80176109d
--- /dev/null
+++ b/src/app/system/manage-surveys/create-survey/create-survey.component.spec.ts
@@ -0,0 +1,25 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { CreateSurveyComponent } from './create-survey.component';
+
+describe('CreateSurveyComponent', () => {
+ let component: CreateSurveyComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ CreateSurveyComponent ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(CreateSurveyComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/system/manage-surveys/create-survey/create-survey.component.ts b/src/app/system/manage-surveys/create-survey/create-survey.component.ts
new file mode 100644
index 000000000..01aa5d9f5
--- /dev/null
+++ b/src/app/system/manage-surveys/create-survey/create-survey.component.ts
@@ -0,0 +1,192 @@
+/** Angular Imports */
+import { Component, OnInit } from '@angular/core';
+import { FormGroup, FormBuilder, FormArray, Validators } from '@angular/forms';
+import { Router, ActivatedRoute } from '@angular/router';
+import { MatDialog } from '@angular/material';
+import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
+
+/** Custom Services */
+import { SystemService } from '../../system.service';
+
+/** Custom Components */
+import { CancelDialogComponent } from '../../../shared/cancel-dialog/cancel-dialog.component';
+
+/**
+ * Create survey component.
+ */
+@Component({
+ selector: 'mifosx-create-survey',
+ templateUrl: './create-survey.component.html',
+ styleUrls: ['./create-survey.component.scss']
+})
+export class CreateSurveyComponent implements OnInit {
+
+ /** Survey form. */
+ surveyForm: FormGroup;
+
+ /**
+ * @param {FormBuilder} formBuilder Form Builder.
+ * @param {SystemService} systemService System Service.
+ * @param {ActivatedRoute} route Activated Route.
+ * @param {Router} router Router for navigation.
+ * @param {MatDialog} dialog Dialog reference.
+ */
+ constructor(private formBuilder: FormBuilder,
+ private systemService: SystemService,
+ private route: ActivatedRoute,
+ private router: Router,
+ public dialog: MatDialog) { }
+
+ /**
+ * Creates the survey form.
+ */
+ ngOnInit() {
+ this.createSurveyForm();
+ }
+
+ /**
+ * Creates the survey form.
+ */
+ createSurveyForm() {
+ this.surveyForm = this.formBuilder.group({
+ 'key': ['', Validators.required],
+ 'name': ['', Validators.required],
+ 'countryCode': ['', [Validators.required, Validators.pattern('^\\s*([A-Za-z]{2})?\\s*$')]],
+ 'description': [''],
+ 'questionDatas': this.formBuilder.array([])
+ });
+ }
+
+ /**
+ * Gets the questions form array.
+ * @returns {FormArray} Questions form array.
+ */
+ get questionDatas(): FormArray {
+ return this.surveyForm.get('questionDatas') as FormArray;
+ }
+
+ /**
+ * Gets the responses form array.
+ * @param {number} questionIndex Index of question to retrieve responses from.
+ * @returns {FormArray} Responses form array.
+ */
+ getResponseDatas(questionIndex: number): FormArray {
+ return this.surveyForm.get(['questionDatas', questionIndex, 'responseDatas']) as FormArray;
+ }
+
+ /**
+ * Creates a question form group
+ * @returns {FormGroup} Question form group.
+ */
+ createQuestionForm(): FormGroup {
+ return this.formBuilder.group({
+ 'key': ['', Validators.required],
+ 'text': ['', Validators.required],
+ 'description': [''],
+ 'responseDatas': this.formBuilder.array([this.createResponseForm()]),
+ 'sequenceNo': ['']
+ });
+ }
+
+ /**
+ * Adds a question to the questions form array
+ */
+ addQuestion() {
+ this.questionDatas.push(this.createQuestionForm());
+ this.updateSequenceNumber();
+ }
+
+ /**
+ * Removes the particular question form from the questions form array at given index.
+ * @param {number} index Array index from where question form needs to be removed.
+ */
+ removeQuestion(index: number) {
+ this.questionDatas.removeAt(index);
+ this.updateSequenceNumber();
+ }
+
+ /**
+ * Creates a response form group
+ * @returns {FormGroup} Response form group.
+ */
+ createResponseForm(): FormGroup {
+ return this.formBuilder.group({
+ 'text': ['', Validators.required],
+ 'value': ['', [Validators.required, Validators.pattern('^\\s*[-]?\\d{0,4}\\s*$')]],
+ 'sequenceNo': ['']
+ });
+ }
+
+ /**
+ * Adds a response to the responses form array of the question with the given Index
+ * @param {number} questionIndex Index of question to add response to.
+ */
+ addResponse(questionIndex: number) {
+ this.getResponseDatas(questionIndex).push(this.createResponseForm());
+ this.updateSequenceNumber();
+ }
+
+ /**
+ * Removes the particular response form from the given responses form array at given index.
+ * @param {FormArray} responseFormArray Given responses form array.
+ * @param {number} index Array index from where response form needs to be removed.
+ */
+ removeResponse(responseFormArray: FormArray, index: number) {
+ responseFormArray.removeAt(index);
+ this.updateSequenceNumber();
+ }
+
+ /**
+ * Updates the sequence numbers of questions and responses
+ */
+ updateSequenceNumber() {
+ for (let questionIndex = 0; questionIndex < this.questionDatas.length; questionIndex++) {
+ this.questionDatas.at(questionIndex).get('sequenceNo').setValue(questionIndex + 1);
+ for (let responseIndex = 0; responseIndex < this.getResponseDatas(questionIndex).length; responseIndex++) {
+ this.getResponseDatas(questionIndex).at(responseIndex).get('sequenceNo').setValue(responseIndex + 1);
+ }
+ }
+ }
+
+ /**
+ * Cancels the survey and redirects to surveys.
+ */
+ cancelSurvey() {
+ const cancelSurveyDialogRef = this.dialog.open(CancelDialogComponent);
+ cancelSurveyDialogRef.afterClosed().subscribe((response: any) => {
+ if (response.cancel) {
+ this.router.navigate(['../'], { relativeTo: this.route });
+ }
+ });
+ }
+
+ /**
+ * Reorders the question order according to the user drop
+ */
+ dropQuestion(event: CdkDragDrop) {
+ moveItemInArray(this.questionDatas.controls, event.previousIndex, event.currentIndex);
+ this.updateSequenceNumber();
+ }
+
+ /**
+ * Reorders the response order according to the user drop
+ */
+ dropResponse(event: CdkDragDrop, questionIndex: number) {
+ moveItemInArray(this.getResponseDatas(questionIndex).controls, event.previousIndex, event.currentIndex);
+ this.updateSequenceNumber();
+ }
+
+ /**
+ * Submits the survey form and creates survey,
+ * if successful redirects to surveys.
+ */
+ submit() {
+ this.surveyForm.patchValue({
+ countryCode: this.surveyForm.value.countryCode.toUpperCase()
+ });
+ this.systemService.createSurvey(this.surveyForm.value).subscribe((response: any) => {
+ this.router.navigate(['../'], { relativeTo: this.route });
+ });
+ }
+
+}
diff --git a/src/app/system/manage-surveys/manage-surveys.component.html b/src/app/system/manage-surveys/manage-surveys.component.html
index 4ab7395a1..63f277807 100644
--- a/src/app/system/manage-surveys/manage-surveys.component.html
+++ b/src/app/system/manage-surveys/manage-surveys.component.html
@@ -1,5 +1,5 @@
-