From 14516d2ac2e8f6be4dbac4af5e77281e84060379 Mon Sep 17 00:00:00 2001 From: Karan Takalkar Date: Mon, 1 Jun 2020 21:48:51 +0530 Subject: [PATCH] feat: add view sms campaign page (#835) Fixes: #563 Co-authored-by: Ashutosh Sharma --- .../organization-routing.module.ts | 26 +++- src/app/organization/organization.module.ts | 4 +- src/app/organization/organization.service.ts | 22 +++ .../common-resolvers/sms-campaign.resolver.ts | 31 ++++ .../sms-campaigns.resolver.ts | 2 +- .../sms-campaigns.component.html | 2 +- .../view-campaign.component.html | 125 +++++++++++++++++ .../view-campaign.component.scss | 21 +++ .../view-campaign.component.spec.ts | 25 ++++ .../view-campaign/view-campaign.component.ts | 132 ++++++++++++++++++ 10 files changed, 382 insertions(+), 8 deletions(-) create mode 100644 src/app/organization/sms-campaigns/common-resolvers/sms-campaign.resolver.ts rename src/app/organization/sms-campaigns/{ => common-resolvers}/sms-campaigns.resolver.ts (90%) create mode 100644 src/app/organization/sms-campaigns/view-campaign/view-campaign.component.html create mode 100644 src/app/organization/sms-campaigns/view-campaign/view-campaign.component.scss create mode 100644 src/app/organization/sms-campaigns/view-campaign/view-campaign.component.spec.ts create mode 100644 src/app/organization/sms-campaigns/view-campaign/view-campaign.component.ts diff --git a/src/app/organization/organization-routing.module.ts b/src/app/organization/organization-routing.module.ts index cf195d811..98e78cea0 100644 --- a/src/app/organization/organization-routing.module.ts +++ b/src/app/organization/organization-routing.module.ts @@ -38,6 +38,7 @@ import { ViewHolidaysComponent } from './holidays/view-holidays/view-holidays.co import { ViewOfficeComponent } from './offices/view-office/view-office.component'; import { GeneralTabComponent } from './offices/view-office/general-tab/general-tab.component'; import { DatatableTabsComponent } from './offices/view-office/datatable-tabs/datatable-tabs.component'; +import { ViewCampaignComponent } from './sms-campaigns/view-campaign/view-campaign.component'; /** Custom Resolvers */ import { LoanProvisioningCriteriaResolver } from './loan-provisioning-criteria/loan-provisioning-criteria.resolver'; @@ -46,7 +47,7 @@ import { EmployeesResolver } from './employees/employees.resolver'; import { EmployeeResolver } from './employees/employee.resolver'; import { EditEmployeeResolver } from './employees/edit-employee.resolver'; import { CurrenciesResolver } from './currencies/currencies.resolver'; -import { SmsCampaignsResolver } from './sms-campaigns/sms-campaigns.resolver'; +import { SmsCampaignsResolver } from './sms-campaigns/common-resolvers/sms-campaigns.resolver'; import { AdhocQueriesResolver } from './adhoc-query/adhoc-queries.resolver'; import { AdhocQueryResolver } from './adhoc-query/adhoc-query.resolver'; import { TellersResolver } from './tellers/tellers.resolver'; @@ -66,6 +67,7 @@ import { HolidayResolver } from './holidays/holiday.resolver'; import { OfficeResolver } from './offices/common-resolvers/office.resolver'; import { OfficeDatatableResolver } from './offices/common-resolvers/office-datatable.resolver'; import { OfficeDatatablesResolver } from './offices/common-resolvers/office-datatables.resolver'; +import { SmsCampaignResolver } from './sms-campaigns/common-resolvers/sms-campaign.resolver'; /** Organization Routes */ const routes: Routes = [ @@ -222,11 +224,24 @@ const routes: Routes = [ }, { path: 'sms-campaigns', - component: SmsCampaignsComponent, data: { title: extract('SMS Campaigns'), breadcrumb: 'SMS Campaigns' }, - resolve: { - smsCampaigns: SmsCampaignsResolver - } + children: [ + { + path: '', + component: SmsCampaignsComponent, + resolve: { + smsCampaigns: SmsCampaignsResolver + } + }, + { + path: ':id', + component: ViewCampaignComponent, + data: { title: extract('View SMS Campaign'), routeResolveBreadcrumb: ['smsCampaign', 'campaignName'] }, + resolve: { + smsCampaign: SmsCampaignResolver + } + } + ] }, { path: 'adhoc-query', @@ -421,6 +436,7 @@ const routes: Routes = [ EditEmployeeResolver, CurrenciesResolver, SmsCampaignsResolver, + SmsCampaignResolver, AdhocQueriesResolver, AdhocQueryResolver, TellersResolver, diff --git a/src/app/organization/organization.module.ts b/src/app/organization/organization.module.ts index 8ce02a66a..60a5546ec 100644 --- a/src/app/organization/organization.module.ts +++ b/src/app/organization/organization.module.ts @@ -41,6 +41,7 @@ import { GeneralTabComponent } from './offices/view-office/general-tab/general-t import { DatatableTabsComponent } from './offices/view-office/datatable-tabs/datatable-tabs.component'; import { SingleRowComponent } from './offices/view-office/datatable-tabs/single-row/single-row.component'; import { MultiRowComponent } from './offices/view-office/datatable-tabs/multi-row/multi-row.component'; +import { ViewCampaignComponent } from './sms-campaigns/view-campaign/view-campaign.component'; /** * Organization Module @@ -87,7 +88,8 @@ import { MultiRowComponent } from './offices/view-office/datatable-tabs/multi-ro GeneralTabComponent, DatatableTabsComponent, SingleRowComponent, - MultiRowComponent + MultiRowComponent, + ViewCampaignComponent ] }) export class OrganizationModule { } diff --git a/src/app/organization/organization.service.ts b/src/app/organization/organization.service.ts index 170c73d0d..722cd2f01 100644 --- a/src/app/organization/organization.service.ts +++ b/src/app/organization/organization.service.ts @@ -173,6 +173,28 @@ export class OrganizationService { return this.http.get('/smscampaigns'); } + /** + * @param {string} smsCampaignId SMS Campaign ID of SMS Campaign. + * @returns {Observable} SMS Campaign. + */ + getSmsCampaign(smsCampaignId: string): Observable { + return this.http.get(`/smscampaigns/${smsCampaignId}`); + } + + /** + * @param {any} SMS + * @returns {Observable} Messages Data + */ + getMessagebyStatus(SMS: any): Observable { + let httpParams = new HttpParams() + .set('status', SMS.status.toString()) + .set('locale', SMS.locale) + .set('dateFormat', SMS.dateFormat); + httpParams = SMS.fromDate ? httpParams.set('fromDate', SMS.fromDate) : httpParams; + httpParams = SMS.toDate ? httpParams.set('toDate', SMS.toDate) : httpParams; + return this.http.get(`/sms/${SMS.id}/messageByStatus`, { params: httpParams }); + } + /** * @returns {Observable} Adhoc Queries data */ diff --git a/src/app/organization/sms-campaigns/common-resolvers/sms-campaign.resolver.ts b/src/app/organization/sms-campaigns/common-resolvers/sms-campaign.resolver.ts new file mode 100644 index 000000000..4845b38c8 --- /dev/null +++ b/src/app/organization/sms-campaigns/common-resolvers/sms-campaign.resolver.ts @@ -0,0 +1,31 @@ +/** Angular Imports */ +import { Injectable } from '@angular/core'; +import { Resolve, ActivatedRouteSnapshot } from '@angular/router'; + +/** rxjs Imports */ +import { Observable } from 'rxjs'; + +/** Custom Services */ +import { OrganizationService } from 'app/organization/organization.service'; + +/** + * SMS Campaign data resolver. + */ +@Injectable() +export class SmsCampaignResolver implements Resolve { + + /** + * @param {OrganizationService} organizationService Organization service. + */ + constructor(private organizationService: OrganizationService) {} + + /** + * Returns the SMS Campaign data. + * @returns {Observable} + */ + resolve(route: ActivatedRouteSnapshot): Observable { + const smsCampaignId = route.paramMap.get('id'); + return this.organizationService.getSmsCampaign(smsCampaignId); + } + +} diff --git a/src/app/organization/sms-campaigns/sms-campaigns.resolver.ts b/src/app/organization/sms-campaigns/common-resolvers/sms-campaigns.resolver.ts similarity index 90% rename from src/app/organization/sms-campaigns/sms-campaigns.resolver.ts rename to src/app/organization/sms-campaigns/common-resolvers/sms-campaigns.resolver.ts index b7ad29b59..63d5ac14f 100644 --- a/src/app/organization/sms-campaigns/sms-campaigns.resolver.ts +++ b/src/app/organization/sms-campaigns/common-resolvers/sms-campaigns.resolver.ts @@ -6,7 +6,7 @@ import { Resolve } from '@angular/router'; import { Observable } from 'rxjs'; /** Custom Services */ -import { OrganizationService } from '../organization.service'; +import { OrganizationService } from '../../organization.service'; /** * SMS Campaigns data resolver. diff --git a/src/app/organization/sms-campaigns/sms-campaigns.component.html b/src/app/organization/sms-campaigns/sms-campaigns.component.html index e647f9cd2..d773fe4ec 100644 --- a/src/app/organization/sms-campaigns/sms-campaigns.component.html +++ b/src/app/organization/sms-campaigns/sms-campaigns.component.html @@ -55,7 +55,7 @@ - + diff --git a/src/app/organization/sms-campaigns/view-campaign/view-campaign.component.html b/src/app/organization/sms-campaigns/view-campaign/view-campaign.component.html new file mode 100644 index 000000000..b46c835a5 --- /dev/null +++ b/src/app/organization/sms-campaigns/view-campaign/view-campaign.component.html @@ -0,0 +1,125 @@ +
+ +
+ + + + + + + + + + + + + + + +
+ + + + + + + + + +
+ + + + Campaign Name : {{ smsCampaignData.campaignName }} + + + Report Name : {{ smsCampaignData.reportName }} + + + Status : {{ smsCampaignData.campaignStatus.value }} + + + Trigger Type : {{ smsCampaignData.triggerType.value }} + + + Submitted on : {{ smsCampaignData.smsCampaignTimeLine.submittedOnDate | date}} + +
+

Template Message :

+ +
+
+ +
+ +
+ + + +
+ +
+
+ + From Date + + + + + + To Date + + + + +
+ +
+
+
+ +
+ + + + + + + + + + + + + + + + + + + +
Message {{sms.message}} Status {{sms.status.value}} Mobile No. {{sms.mobileNo}} Campaign Name {{sms.campaignName}}
+
+ +
+ +
+ +
+ +
+ +
+ +
diff --git a/src/app/organization/sms-campaigns/view-campaign/view-campaign.component.scss b/src/app/organization/sms-campaigns/view-campaign/view-campaign.component.scss new file mode 100644 index 000000000..54a08a1e6 --- /dev/null +++ b/src/app/organization/sms-campaigns/view-campaign/view-campaign.component.scss @@ -0,0 +1,21 @@ +.action-buttons { + width: 88.75%; +} +.sms-card { + margin: 0 auto; + width: 77.5%; + padding: 0; + .tab-content { + padding: 1%; + margin: 1%; + .template-message { + padding-inline: 1.5%; + margin-top: 1%; + } + .search-button { + max-width: 3%; + max-height: 2%; + padding-block: 2.25%; + } + } +} diff --git a/src/app/organization/sms-campaigns/view-campaign/view-campaign.component.spec.ts b/src/app/organization/sms-campaigns/view-campaign/view-campaign.component.spec.ts new file mode 100644 index 000000000..248a518c1 --- /dev/null +++ b/src/app/organization/sms-campaigns/view-campaign/view-campaign.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ViewCampaignComponent } from './view-campaign.component'; + +describe('ViewCampaignComponent', () => { + let component: ViewCampaignComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ViewCampaignComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ViewCampaignComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/organization/sms-campaigns/view-campaign/view-campaign.component.ts b/src/app/organization/sms-campaigns/view-campaign/view-campaign.component.ts new file mode 100644 index 000000000..ca966fbc0 --- /dev/null +++ b/src/app/organization/sms-campaigns/view-campaign/view-campaign.component.ts @@ -0,0 +1,132 @@ +/** Angular Imports */ +import { Component, OnInit, ViewChild } from '@angular/core'; +import { FormGroup, FormBuilder } from '@angular/forms'; +import { MatTableDataSource, MatTable } from '@angular/material'; +import { ActivatedRoute } from '@angular/router'; +import { DatePipe } from '@angular/common'; + +/** Custom Services */ +import { OrganizationService } from '../../organization.service'; + +/** + * View SMS Campaign Component + */ +@Component({ + selector: 'mifosx-view-campaign', + templateUrl: './view-campaign.component.html', + styleUrls: ['./view-campaign.component.scss'] +}) +export class ViewCampaignComponent implements OnInit { + + /** Minimum date allowed. */ + minDate = new Date(2000, 0, 1); + /** Maximum date allowed. */ + maxDate = new Date(); + /** SMS form. */ + smsForm: FormGroup; + /** SMS Campaign data. */ + smsCampaignData: any; + /** Message Status */ + status: any; + /** Data Table Columns */ + displayedColumns: string[] = ['Message', 'Status', 'Mobile No.', 'Campaign Name']; + /** Data source for SMS campaigns table. */ + dataSource = new MatTableDataSource(); + + /** Message Table Reference */ + @ViewChild('messageTable') messageTableRef: MatTable; + + /** SMS Camapaign Tabs */ + smsTabs: any[] = [ + { + label: 'Pending SMS', + status: 100 + }, + { + label: 'Waiting for Delivery Report', + status: 150 + }, + { + label: 'Sent SMS', + status: 200 + }, + { + label: 'Delivered SMS', + status: 300 + }, + { + label: 'Failed SMS', + status: 400 + } + ]; + + /** + * Retrieves the SMS Campaign data from `resolve` + * @param {ActivatedRoute} route Activated Route + * @param {FormBuilder} formBuilder Form Builder + * @param {DatePipe} datePipe Date Pipe + * @param {OrganizationService} organizationService Organization Service + */ + constructor(private route: ActivatedRoute, + private formBuilder: FormBuilder, + private datePipe: DatePipe, + private organizationService: OrganizationService) { + this.route.data.subscribe((data: { smsCampaign: any }) => { + this.smsCampaignData = data.smsCampaign; + }); + } + + + ngOnInit() { + this.createSMSForm(); + } + + /** + * Creates the SMS form. + */ + createSMSForm() { + this.smsForm = this.formBuilder.group({ + 'fromDate': [''], + 'toDate': [''], + }); + } + + /** + * Sets status for messages on tab change. + * Clears data in messages table if any. + * Resets the search form. + * @param {any} $event Tab change event. + */ + onTabChange($event: any) { + const selectedTabName = $event.tab ? $event.tab.textLabel : 'Campaign'; + const tab = this.smsTabs.find((entry: any) => selectedTabName === entry.label); + this.status = tab ? tab.status : undefined; + this.dataSource.data = []; + this.messageTableRef.renderRows(); + this.smsForm.reset(); + } + + /** + * Retrives messages by status. + */ + search() { + const prevFromDate: Date = this.smsForm.value.fromDate; + const prevToDate: Date = this.smsForm.value.toDate; + // TODO: Update once language and date settings are setup + const dateFormat = 'yyyy-MM-dd'; + this.smsForm.patchValue({ + fromDate: this.datePipe.transform(prevFromDate, dateFormat), + toDate: this.datePipe.transform(prevToDate, dateFormat) + }); + const SMS = this.smsForm.value; + SMS.id = this.smsCampaignData.id; + SMS.locale = 'en'; + SMS.dateFormat = dateFormat; + SMS.status = this.status; + this.organizationService.getMessagebyStatus(SMS).subscribe((response: any) => { + this.dataSource.data = response.pageItems; + this.messageTableRef.renderRows(); + }); + } + +}