refractor: self service module (#291)

* Refractor components.
* Improve responsiveness of components.
* Add task management component.
* Add users data resolver.
* Add relative router links.
* Replace mat-icons by font-awesome icons.
* Add comments.

Fixes #290
This commit is contained in:
Abhay Chawla
2018-08-12 14:10:16 +05:30
committed by GitHub
parent 90087bf248
commit 116d05a7d1
30 changed files with 716 additions and 427 deletions
@@ -52,7 +52,7 @@ export class BreadcrumbComponent implements OnInit {
/**
* Generates the breadcrumbs.
* @param {ActivatedRoute} activatedRoute Activate Route.
* @param {ActivatedRoute} activatedRoute Activated Route.
* @param {Router} router Router for navigation.
*/
constructor(private activatedRoute: ActivatedRoute,
+1
View File
@@ -56,6 +56,7 @@ export class ShellComponent implements OnInit, OnDestroy {
*/
toggleCollapse($event: boolean) {
this.sidenavCollapsed = $event;
this.cdr.detectChanges();
}
/**
@@ -110,7 +110,7 @@
<mat-menu #selfServiceMenu="matMenu" [overlapTrigger]="false">
<button mat-menu-item [routerLink]="['/self-service/users']">User Management</button>
<button mat-menu-item [routerLink]="['/self-service/app-configuration']">App Configuration</button>
<button mat-menu-item>Task Management</button>
<button mat-menu-item [routerLink]="['/self-service/task-management']">Task Management</button>
</mat-menu>
<!-- Application User Help Menu -->
@@ -1,4 +1,4 @@
<mat-card class="container">
<div class="container">
<mat-accordion>
@@ -13,29 +13,34 @@
<div fxLayout="column">
<mat-form-field>
<input matInput placeholder="Name of the Organisation">
<mat-label>Name of the Organisation</mat-label>
<input matInput>
</mat-form-field>
<mat-form-field>
<textarea matInput placeholder="Description"></textarea>
<mat-label>Description</mat-label>
<textarea matInput></textarea>
</mat-form-field>
<mat-form-field>
<textarea matInput placeholder="Summary"></textarea>
<mat-label>Summary</mat-label>
<textarea matInput></textarea>
</mat-form-field>
<mat-form-field>
<mat-select placeholder="Default Language">
<mat-option *ngFor="let language of languages" [value]="language.value">
{{ language.viewValue }}
<mat-label>Default Language</mat-label>
<mat-select>
<mat-option *ngFor="let language of languages" [value]="language">
{{ language }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-select placeholder="Default Date Format">
<mat-option *ngFor="let dateFormat of dateFormats" [value]="dateFormat.value">
{{ dateFormat.viewValue }}
<mat-label>Default Date Format</mat-label>
<mat-select>
<mat-option *ngFor="let dateFormat of dateFormats" [value]="dateFormat">
{{ dateFormat }}
</mat-option>
</mat-select>
</mat-form-field>
@@ -54,10 +59,17 @@
<div fxLayout="column">
Favicon <mifosx-file-upload></mifosx-file-upload>
Cover Image <mifosx-file-upload></mifosx-file-upload>
Logo <mifosx-file-upload></mifosx-file-upload>
Logo with Organisation Name <mifosx-file-upload></mifosx-file-upload>
<span class="header">Favicon</span>
<mifosx-file-upload></mifosx-file-upload>
<span class="header">Cover Image</span>
<mifosx-file-upload></mifosx-file-upload>
<span class="header">Logo</span>
<mifosx-file-upload></mifosx-file-upload>
<span class="header">Logo with Organisation Name</span>
<mifosx-file-upload></mifosx-file-upload>
</div>
@@ -73,36 +85,40 @@
<div fxLayout="column">
Mobile Banking App
<span class="header">Mobile Banking App</span>
<mat-form-field>
<mat-select placeholder="Default Theme">
<mat-option *ngFor="let theme of mobileAppThemes" [value]="theme.value">
{{ theme.viewValue }}
<mat-label>Default Theme</mat-label>
<mat-select>
<mat-option *ngFor="let theme of mobileAppThemes" [value]="theme">
{{ theme }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-select placeholder="Default Font">
<mat-option *ngFor="let font of mobileAppFonts" [value]="font.value">
{{ font.viewValue }}
<mat-label>Default Font</mat-label>
<mat-select>
<mat-option *ngFor="let font of mobileAppFonts" [value]="font">
{{ font }}
</mat-option>
</mat-select>
</mat-form-field>
Online Banking App
<span class="header">Online Banking App</span>
<mat-form-field>
<mat-select placeholder="Default Theme">
<mat-option *ngFor="let theme of onlineBankingAppThemes" [value]="theme.value">
{{ theme.viewValue }}
<mat-label>Default Theme</mat-label>
<mat-select>
<mat-option *ngFor="let theme of onlineBankingAppThemes" [value]="theme">
{{ theme }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-select placeholder="Default Font">
<mat-option *ngFor="let font of onlineBankingAppFonts" [value]="font.value">
{{ font.viewValue }}
<mat-label>Default Font</mat-label>
<mat-select>
<mat-option *ngFor="let font of onlineBankingAppFonts" [value]="font">
{{ font }}
</mat-option>
</mat-select>
</mat-form-field>
@@ -122,15 +138,18 @@
<div fxLayout="column">
<mat-form-field>
<input type="url" matInput placeholder="Website">
<mat-label>Website</mat-label>
<input type="url" matInput>
</mat-form-field>
<mat-form-field>
<input type="email" matInput placeholder="Email">
<mat-label>Email</mat-label>
<input type="email" matInput>
</mat-form-field>
<mat-form-field>
<input type="tel" matInput placeholder="Contact No">
<mat-label>Contact No</mat-label>
<input type="tel" matInput>
</mat-form-field>
</div>
@@ -139,4 +158,4 @@
</mat-accordion>
</mat-card>
</div>
@@ -0,0 +1,3 @@
.header {
font-weight: 500;
}
@@ -1,5 +1,11 @@
/** Angular Imports */
import { Component, OnInit } from '@angular/core';
/**
* Self service app configuration component.
*
* TODO: Complete functionality once API is available.
*/
@Component({
selector: 'mifosx-app-configuration',
templateUrl: './app-configuration.component.html',
@@ -7,12 +13,18 @@ import { Component, OnInit } from '@angular/core';
})
export class AppConfigurationComponent implements OnInit {
languages: string[];
dateFormats: string[];
mobileAppThemes: string[];
mobileAppFonts: string[];
onlineBankingAppThemes: string[];
onlineBankingAppFonts: string[];
/** Placeholder for languages. */
languages: any;
/** Placeholder for date formats. */
dateFormats: any;
/** Placeholder for mobile app themes. */
mobileAppThemes: any;
/** Placeholder for mobile app fonts. */
mobileAppFonts: any;
/** Placeholder for online banking app themes. */
onlineBankingAppThemes: any;
/** Placeholder for online banking app fonts. */
onlineBankingAppFonts: any;
constructor() { }
@@ -1,15 +1,27 @@
/** Angular Imports */
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { Route, extract } from '../core';
/** Routing Imports */
import { Route } from '../core';
/** Translation Imports */
import { extract } from '../core';
/** Custom Components */
import { SelfServiceComponent } from './self-service.component';
import { UsersComponent } from './users/users.component';
import { CreateUserComponent } from './users/create-user/create-user.component';
import { ViewUserComponent } from './users/view-user/view-user.component';
import { EditUserComponent } from './users/edit-user/edit-user.component';
import { AppConfigurationComponent } from './app-configuration/app-configuration.component';
import { SelfServiceComponent } from './self-service.component';
import { TaskManagementComponent } from './task-management/task-management.component';
/** Custom Resolvers */
import { UsersResolver } from './users/users.resolver';
import { ViewUserResolver } from './users/view-user/view-user.resolver';
/** Self Service Admin Portal Routes */
const routes: Routes = [
Route.withShell([
{
@@ -23,7 +35,10 @@ const routes: Routes = [
children: [
{
path: '',
component: UsersComponent
component: UsersComponent,
resolve: {
users: UsersResolver
}
},
{
path: 'create',
@@ -53,16 +68,29 @@ const routes: Routes = [
{
path: 'app-configuration',
component: AppConfigurationComponent,
data: { title: extract('App Configuration'), breadcrumb: 'App Configuration' },
data: { title: extract('Self Service App Configuration'), breadcrumb: 'App Configuration' }
},
{
path: 'task-management',
component: TaskManagementComponent,
data: { title: extract('Self Service Task Management'), breadcrumb: 'Task Management' }
}
]
}
])
];
/**
* Self Service Routing Module
*
* Configures the self service admin portal routes.
*/
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
providers: [ViewUserResolver]
providers: [
UsersResolver,
ViewUserResolver
]
})
export class SelfServiceRoutingModule { }
@@ -1,5 +1,11 @@
/** Angular Imports */
import { Component, OnInit } from '@angular/core';
/**
* Self service component.
*
* All components related to self service admin portal are routed here.
*/
@Component({
selector: 'mifosx-self-service',
templateUrl: './self-service.component.html',
+18 -14
View File
@@ -1,23 +1,29 @@
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { CommonModule } from '@angular/common';
/** Angular Imports */
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { CoreModule } from '../core/core.module';
/** Custom Modules */
import { SharedModule } from '../shared/shared.module';
import { SelfServiceRoutingModule } from './self-service-routing.module';
/** Custom Components */
import { SelfServiceComponent } from './self-service.component';
import { UsersComponent } from './users/users.component';
import { CreateUserComponent } from './users/create-user/create-user.component';
import { ViewUserComponent } from './users/view-user/view-user.component';
import { EditUserComponent } from './users/edit-user/edit-user.component';
import { AppConfigurationComponent } from './app-configuration/app-configuration.component';
import { SharedModule } from '../shared/shared.module';
import { SelfServiceComponent } from './self-service.component';
import { UsersComponent } from './users/users.component';
import { TaskManagementComponent } from './task-management/task-management.component';
/**
* Self Service Module
*
* All components related to self service admin portal functions should be declared here.
*/
@NgModule({
imports: [
CommonModule,
CoreModule,
FormsModule,
SharedModule,
FormsModule,
SelfServiceRoutingModule
],
declarations: [
@@ -26,10 +32,8 @@ import { UsersComponent } from './users/users.component';
CreateUserComponent,
ViewUserComponent,
EditUserComponent,
AppConfigurationComponent
],
schemas: [
CUSTOM_ELEMENTS_SCHEMA
],
AppConfigurationComponent,
TaskManagementComponent
]
})
export class SelfServiceModule { }
@@ -0,0 +1,7 @@
<div class="container">
<p>
TODO: task-management component.
</p>
</div>
@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { TaskManagementComponent } from './task-management.component';
describe('TaskManagementComponent', () => {
let component: TaskManagementComponent;
let fixture: ComponentFixture<TaskManagementComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ TaskManagementComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TaskManagementComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'mifosx-task-management',
templateUrl: './task-management.component.html',
styleUrls: ['./task-management.component.scss']
})
export class TaskManagementComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
@@ -1,140 +1,148 @@
<mat-card class="container m-t-40">
<div class="container" [class.small-width-container]="userType.value === 'Existing User'">
<mat-card-header>
<mat-radio-group class="example-radio-group" [(ngModel)]="currentUserType" fxLayout="row" fxLayoutGap="50px">
<mat-radio-button class="example-radio-button" *ngFor="let userType of userTypes" [value]="userType">
{{ userType }}
</mat-radio-button>
</mat-radio-group>
</mat-card-header>
<mat-card>
<ng-container *ngIf="currentUserType === 'Existing User'">
<mat-card-header class="m-b-20">
<mat-radio-group fxLayout="row" fxLayoutGap="20px" [formControl]="userType">
<mat-radio-button *ngFor="let type of userTypes" [value]="type">
{{ type }}
</mat-radio-button>
</mat-radio-group>
</mat-card-header>
<mat-card-content class="m-t-20">
<form fxLayout="column" fxLayoutGap="10px">
<mat-form-field>
<mat-select placeholder="Office">
<mat-option *ngFor="let office of officeData" [value]="office.value">
{{ office.viewValue }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-select placeholder="Staff">
<mat-option *ngFor="let staff of staffData" [value]="staff.value">
{{ staff.viewValue }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-select placeholder="Client">
<mat-option *ngFor="let client of clientData" [value]="client.value">
{{ client.viewValue }}
</mat-option>
</mat-select>
</mat-form-field>
</form>
</mat-card-content>
<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
<button mat-raised-button color="primary"><mat-icon>lock_open</mat-icon>&nbsp;&nbsp;Activate Self Service User</button>
<button mat-raised-button>Cancel</button>
</mat-card-actions>
</ng-container>
<ng-container *ngIf="currentUserType === 'New User'">
<mat-card-content class="m-t-20">
<div *ngIf="userType.value === 'Existing User'">
<form>
<mat-grid-list cols="2" rowHeight="80px"> <!-- TODO: Dynamic columns to make responsive and hide the blank tile or find some other way -->
<mat-grid-tile>
<mat-form-field fxFlex class="m-10">
<mat-select placeholder="Office">
<mat-option *ngFor="let office of officeData" [value]="office.value">
{{ office.viewValue }}
<mat-card-content>
<div fxLayout="column">
<mat-form-field>
<mat-label>Office</mat-label>
<mat-select>
<mat-option *ngFor="let office of officeData" [value]="office">
{{ office }}
</mat-option>
</mat-select>
</mat-form-field>
</mat-grid-tile>
<mat-grid-tile>
<mat-form-field fxFlex class="m-10">
<mat-select placeholder="Staff">
<mat-option *ngFor="let staff of staffData" [value]="staff.value">
{{ staff.viewValue }}
<mat-form-field>
<mat-label>Staff</mat-label>
<mat-select>
<mat-option *ngFor="let staff of staffData" [value]="staff">
{{ staff }}
</mat-option>
</mat-select>
</mat-form-field>
</mat-grid-tile>
<mat-grid-tile>
<mat-form-field fxFlex class="m-10">
<input matInput placeholder="Username">
</mat-form-field>
</mat-grid-tile>
<mat-grid-tile>
</mat-grid-tile>
<mat-grid-tile>
<mat-form-field fxFlex class="m-10">
<input matInput placeholder="First Name">
</mat-form-field>
</mat-grid-tile>
<mat-grid-tile>
<mat-form-field fxFlex class="m-10">
<input matInput placeholder="Last Name">
</mat-form-field>
</mat-grid-tile>
<mat-grid-tile>
<mat-form-field fxFlex class="m-10">
<mat-select placeholder="Gender">
<mat-option *ngFor="let gender of genderData" [value]="gender.value">
{{ gender.viewValue }}
<mat-form-field>
<mat-label>Client</mat-label>
<mat-select>
<mat-option *ngFor="let client of clientData" [value]="client">
{{ client }}
</mat-option>
</mat-select>
</mat-form-field>
</mat-grid-tile>
<mat-grid-tile>
<mat-form-field fxFlex class="m-10">
<input matInput [matDatepicker]="picker" placeholder="Date of Birth">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>
</mat-grid-tile>
</div>
<mat-grid-tile>
<mat-form-field fxFlex class="m-10">
<input matInput placeholder="Email">
</mat-form-field>
</mat-grid-tile>
</mat-card-content>
<mat-grid-tile>
<mat-form-field fxFlex class="m-10">
<input matInput placeholder="Mobile No">
</mat-form-field>
</mat-grid-tile>
</mat-grid-list>
<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
<button type="button" mat-raised-button [routerLink]="['../']">Cancel</button>
<button mat-raised-button color="accent">
<fa-icon icon="lock-open"></fa-icon>&nbsp;&nbsp;
Activate Self Service User
</button>
</mat-card-actions>
</form>
</mat-card-content>
</div>
<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
<button mat-raised-button color="primary"><mat-icon>create</mat-icon>&nbsp;&nbsp;Create Self Service User</button>
<button mat-raised-button>Cancel</button>
</mat-card-actions>
<div *ngIf="userType.value === 'New User'">
</ng-container>
<form>
</mat-card>
<mat-card-content>
<div fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
<mat-form-field fxFlex="48%">
<mat-label>Office</mat-label>
<mat-select>
<mat-option *ngFor="let office of officeData" [value]="office">
{{ office }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="48%">
<mat-label>Staff</mat-label>
<mat-select>
<mat-option *ngFor="let staff of staffData" [value]="staff">
{{ staff }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="48%">
<mat-label>Username</mat-label>
<input type="text" matInput>
</mat-form-field>
<span fxFlex="48%" fxHide.lt-md></span>
<mat-form-field fxFlex="48%">
<mat-label>First Name</mat-label>
<input type="text" matInput>
</mat-form-field>
<mat-form-field fxFlex="48%">
<mat-label>Last Name</mat-label>
<input type="text" matInput>
</mat-form-field>
<mat-form-field fxFlex="48%">
<mat-label>Gender</mat-label>
<mat-select>
<mat-option *ngFor="let gender of genderData" [value]="gender">
{{ gender }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="48%">
<mat-label>Date of Birth</mat-label>
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="dateOfBirthDatePicker">
<mat-datepicker-toggle matSuffix [for]="dateOfBirthDatePicker"></mat-datepicker-toggle>
<mat-datepicker #dateOfBirthDatePicker></mat-datepicker>
</mat-form-field>
<mat-form-field fxFlex="48%">
<mat-label>Email</mat-label>
<input type="email" matInput>
</mat-form-field>
<mat-form-field fxFlex="48%">
<mat-label>Mobile No</mat-label>
<input type="tel" matInput>
</mat-form-field>
</div>
</mat-card-content>
<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
<button type="button" mat-raised-button [routerLink]="['../']">Cancel</button>
<button mat-raised-button color="primary">Submit</button>
</mat-card-actions>
</form>
</div>
</mat-card>
</div>
@@ -0,0 +1,3 @@
.small-width-container {
max-width: 37rem;
}
@@ -1,5 +1,12 @@
/** Angular Imports */
import { Component, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';
/**
* Create self service user component.
*
* TODO: Complete functionality once API is available.
*/
@Component({
selector: 'mifosx-create-user',
templateUrl: './create-user.component.html',
@@ -7,13 +14,22 @@ import { Component, OnInit } from '@angular/core';
})
export class CreateUserComponent implements OnInit {
isCollapsed = false;
/** Denotes type of user. */
userTypes = ['Existing User', 'New User'];
currentUserType = this.userTypes[0];
officeData: string[];
staffData: string[];
clientData: string[];
genderData: string[];
/** Radio button group form control for type of user. */
userType = new FormControl(this.userTypes[0]);
/** Placeholder for office data. */
officeData = ['Office 1', 'Office 2'];
/** Placeholder for staff data. */
staffData = ['Staff 1', 'Staff 2'];
/** Placeholder for client data. */
clientData = ['Client 1', 'Client 2'];
/** Placeholder for gender data. */
genderData = ['Male', 'Female'];
/** Minimum date of birth of user allowed. */
minDate = new Date(1900, 0, 1);
/** Maximum date of birth of user allowed. */
maxDate = new Date();
constructor() { }
@@ -1,94 +1,85 @@
<mat-card class="container m-t-40">
<div class="container">
<mat-card-header>
</mat-card-header>
<mat-card-content class="m-t-20">
<mat-card>
<form>
<mat-grid-list cols="2" rowHeight="80px"> <!-- TODO: Dynamic columns to make responsive and hide the blank tile or find some other way -->
<mat-grid-tile>
<mat-form-field fxFlex class="m-10">
<mat-select placeholder="Office">
<mat-option *ngFor="let office of officeData" [value]="office.value">
{{ office.viewValue }}
<mat-card-content>
<div fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
<mat-form-field fxFlex="48%">
<mat-label>Office</mat-label>
<mat-select>
<mat-option *ngFor="let office of officeData" [value]="office">
{{ office }}
</mat-option>
</mat-select>
</mat-form-field>
</mat-grid-tile>
<mat-grid-tile>
<mat-form-field fxFlex class="m-10">
<mat-select placeholder="Staff">
<mat-option *ngFor="let staff of staffData" [value]="staff.value">
{{ staff.viewValue }}
<mat-form-field fxFlex="48%">
<mat-label>Staff</mat-label>
<mat-select>
<mat-option *ngFor="let staff of staffData" [value]="staff">
{{ staff }}
</mat-option>
</mat-select>
</mat-form-field>
</mat-grid-tile>
<mat-grid-tile>
<mat-form-field fxFlex class="m-10">
<input matInput placeholder="Username">
<mat-form-field fxFlex="48%">
<mat-label>Username</mat-label>
<input type="text" matInput>
</mat-form-field>
</mat-grid-tile>
<mat-grid-tile>
<span fxFlex="48%" fxHide.lt-md></span>
</mat-grid-tile>
<mat-grid-tile>
<mat-form-field fxFlex class="m-10">
<input matInput placeholder="First Name">
<mat-form-field fxFlex="48%">
<mat-label>First Name</mat-label>
<input type="text" matInput>
</mat-form-field>
</mat-grid-tile>
<mat-grid-tile>
<mat-form-field fxFlex class="m-10">
<input matInput placeholder="Last Name">
<mat-form-field fxFlex="48%">
<mat-label>Last Name</mat-label>
<input type="text" matInput>
</mat-form-field>
</mat-grid-tile>
<mat-grid-tile>
<mat-form-field fxFlex class="m-10">
<mat-select placeholder="Gender">
<mat-option *ngFor="let gender of genderData" [value]="gender.value">
{{ gender.viewValue }}
<mat-form-field fxFlex="48%">
<mat-label>Gender</mat-label>
<mat-select>
<mat-option *ngFor="let gender of genderData" [value]="gender">
{{ gender }}
</mat-option>
</mat-select>
</mat-form-field>
</mat-grid-tile>
<mat-grid-tile>
<mat-form-field fxFlex class="m-10">
<input matInput [matDatepicker]="picker" placeholder="Date of Birth">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
<mat-form-field fxFlex="48%">
<mat-label>Date of Birth</mat-label>
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="dateOfBirthDatePicker">
<mat-datepicker-toggle matSuffix [for]="dateOfBirthDatePicker"></mat-datepicker-toggle>
<mat-datepicker #dateOfBirthDatePicker></mat-datepicker>
</mat-form-field>
</mat-grid-tile>
<mat-grid-tile>
<mat-form-field fxFlex class="m-10">
<input matInput placeholder="Email">
<mat-form-field fxFlex="48%">
<mat-label>Email</mat-label>
<input type="email" matInput>
</mat-form-field>
</mat-grid-tile>
<mat-grid-tile>
<mat-form-field fxFlex class="m-10">
<input matInput placeholder="Mobile No">
<mat-form-field fxFlex="48%">
<mat-label>Mobile No</mat-label>
<input type="tel" matInput>
</mat-form-field>
</mat-grid-tile>
</mat-grid-list>
</div>
</mat-card-content>
<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
<button type="button" mat-raised-button [routerLink]="['../']">Cancel</button>
<button mat-raised-button color="primary">Submit</button>
</mat-card-actions>
</form>
</mat-card-content>
</mat-card>
<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
<button mat-raised-button color="primary">Submit</button>
<button mat-raised-button>Cancel</button>
</mat-card-actions>
</mat-card>
</div>
@@ -1,5 +1,11 @@
/** Angular Imports */
import { Component, OnInit } from '@angular/core';
/**
* Edit self service user component.
*
* TODO: Complete functionality once API is available.
*/
@Component({
selector: 'mifosx-edit-user',
templateUrl: './edit-user.component.html',
@@ -7,9 +13,16 @@ import { Component, OnInit } from '@angular/core';
})
export class EditUserComponent implements OnInit {
officeData: string[];
staffData: string[];
genderData: string[];
/** Placeholder for office data. */
officeData: any;
/** Placeholder for staff data. */
staffData: any;
/** Placeholder for gender data. */
genderData: any;
/** Minimum date of birth of user allowed. */
minDate = new Date(1900, 0, 1);
/** Maximum date of birth of user allowed. */
maxDate = new Date();
constructor() { }
+9
View File
@@ -0,0 +1,9 @@
/** Self Service User model. */
export interface User {
id: number;
name: string;
email: string;
isSelfServiceUser: boolean;
officeName: string;
staff: string;
}
+34 -9
View File
@@ -1,32 +1,57 @@
/** Angular Routes */
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/internal/Observable';
import { map } from 'rxjs/internal/operators/map';
import { HttpClient, HttpParams } from '@angular/common/http';
/** rxjs Imports */
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
/** Custom Models */
import { User } from './user.model';
/**
* Self service users service.
*
* TODO: Complete functionality once API is available.
*/
@Injectable({
providedIn: 'root'
})
export class UserService {
/**
* @param {HttpClient} http Http Client to send requests.
*/
constructor(private http: HttpClient) { }
getUsers(): Observable<any> {
return this.http.get<any>(`/users?fields=id,firstname,lastname,email,officeName,staff&tenantIdentifier=default&pretty=true`)
/**
* Gets all the self service users.
*
* TODO: To be replaced once API is available.
*/
getUsers(): Observable<User[]> {
const httpParams = new HttpParams().set('fields', 'id,firstname,lastname,email,officeName,staff');
return this.http.get('/users', { params: httpParams })
.pipe(
map((res) => {
res.forEach((user: any) => {
map((users: any) => {
users.forEach((user: any) => {
user.name = `${user.firstname} ${user.lastname}`;
user.staff = user.staff ? `${user.staff.firstname} ${user.staff.lastname}` : '';
delete user.firstname;
delete user.lastname;
});
return res;
return users as User[];
})
);
}
/**
* Gets a self service user.
*
* TODO: Mock data to be replaced once API is available.
*/
getUser(): Observable<any> {
return this.http.disableApiPrefix().get('http://localhost:4200/assets/mock/user.mock.json');
return this.http.disableApiPrefix().get('/assets/mock/user.mock.json');
}
}
+32 -33
View File
@@ -1,30 +1,29 @@
<mat-card class="container m-t-40">
<div class="container m-b-20" fxLayout="row" fxLayout.lt-md="column" fxLayoutAlign="end" fxLayoutGap="20px">
<!-- TODO: Update to show only Activate/Inactivate button at a time according to selection in table. -->
<button mat-raised-button color="accent">
<fa-icon icon="lock-open"></fa-icon>&nbsp;&nbsp;
Activate
</button>
<button mat-raised-button color="warn">
<fa-icon icon="lock"></fa-icon>&nbsp;&nbsp;
Deactivate
</button>
<button mat-raised-button color="primary" [routerLink]="['create']">
<fa-icon icon="plus"></fa-icon>&nbsp;&nbsp;
Create User
</button>
</div>
<div fxLayout="row" fxLayoutGap="30px" class="m-b-20">
<!-- <mat-card-header> -->
<div class="container">
<!-- <mat-grid-list cols="1" rowHeight="80px">
<mat-grid-tile> -->
<mat-form-field fxFlex>
<input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
</mat-form-field>
<!-- </mat-grid-tile> -->
<!-- <mat-grid-tile> -->
<!-- <mat-card-actions> -->
<!-- <button mat-raised-button color="primary"><mat-icon>lock_open</mat-icon>&nbsp;&nbsp;Activate</button> -->
<!-- <button mat-raised-button color="primary"><mat-icon>lock</mat-icon>&nbsp;&nbsp;Deactivate</button> -->
<button mat-raised-button color="primary" [routerLink]="['/self-service/users/create']"><mat-icon>add</mat-icon>&nbsp;&nbsp;Create User</button>
<!-- </mat-card-actions> -->
<!-- </mat-grid-tile> -->
<!-- </mat-grid-list> -->
<!-- </mat-card-header> -->
<div fxLayout="row">
<mat-form-field fxFlex>
<mat-label>Filter</mat-label>
<input matInput type="text" (keyup)="applyFilter($event.target.value)">
</mat-form-field>
</div>
<mat-card-content class="mat-elevation-z8">
<div class="mat-elevation-z8">
<table mat-table [dataSource]="dataSource" matSort>
@@ -45,46 +44,46 @@
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
<td mat-cell *matCellDef="let user"><span class="mobile-label">Name: </span>{{ user.name }} </td>
<td mat-cell *matCellDef="let user"> {{ user.name }} </td>
</ng-container>
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef mat-sort-header> User ID </th>
<td mat-cell *matCellDef="let user"><span class="mobile-label">User ID: </span>{{ user.id }}</td>
<td mat-cell *matCellDef="let user"> {{ user.id }} </td>
</ng-container>
<ng-container matColumnDef="email">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Email ID </th>
<td mat-cell *matCellDef="let user"><span class="mobile-label">Email ID: </span>{{ user.email }}</td>
<td mat-cell *matCellDef="let user"> {{ user.email }} </td>
</ng-container>
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef mat-sort-header="isSelfServiceUser"> Status </th>
<td mat-cell *matCellDef="let user">
<span class="mobile-label">Status: </span>
<div [className]="user.isSelfServiceUser === true ? 'active' : 'inactive'">
<mat-icon matTooltip="{{ user.isSelfServiceUser === true ? 'Active' : 'Inactive' }}" matTooltipPosition="right">lens</mat-icon>
<fa-icon matTooltip="{{ user.isSelfServiceUser === true ? 'Active' : 'Inactive' }}" matTooltipPosition="right" icon="circle" size="lg"></fa-icon>
</div>
</td>
</ng-container>
<ng-container matColumnDef="officeName">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Office </th>
<td mat-cell *matCellDef="let user"><span class="mobile-label">Office: </span>{{ user.officeName }}</td>
<td mat-cell *matCellDef="let user"> {{ user.officeName }} </td>
</ng-container>
<ng-container matColumnDef="staff">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Staff </th>
<td mat-cell *matCellDef="let user"><span class="mobile-label">Staff: </span>{{ user.staff }}</td>
<td mat-cell *matCellDef="let user"> {{ user.staff }} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;" (click)="selection.toggle(row)"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;" [routerLink]="['view/1600']"></tr>
<!-- TODO: Update route once API is setup. -->
</table>
<mat-paginator [pageSizeOptions]="[10, 25, 50, 100]" showFirstLastButtons></mat-paginator>
</mat-card-content>
</div>
</mat-card>
</div>
@@ -1,53 +1,12 @@
// td, th {
// text-align: center;
// }
// ngb-pagination {
// margin: 20px 0px;
// }
.mat-table {
table {
width: 100%;
}
// .mat-form-field {
// width: 100%;
// }
.mobile-label {
display: none;
}
// TODO: CONFIGURE THESE CLASSES GLOBALLY
.inactive {
color: grey;
color: #d3d3d3;
}
.active {
color: green;
color: #32cd32;
}
// @media(max-width: 600px) {
// .mobile-label {
// width: 80px;
// display: inline-block;
// font-weight: bold;
// }
// .mat-header-row {
// display: none;
// }
// .mat-row {
// display: flex;
// flex-direction: column;
// align-items: start;
// padding: 68px 24px;
// min-height: 108px;
// }
// .mat-cell {
// flex: 1;
// display: flex;
// align-items: center;
// min-height: inherit;
// }
// }
+47 -17
View File
@@ -1,17 +1,20 @@
/** Angular Imports */
import { Component, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { SelectionModel } from '@angular/cdk/collections';
import { MatPaginator, MatSort, MatTableDataSource } from '@angular/material';
/** Custom Services */
import { UserService } from './user.service';
export interface User {
name: string;
id: number;
email: string;
isSelfServiceUser: boolean;
officeName: string;
staff: string;
}
/** Custom Model */
import { User } from './user.model';
/**
* Self service users component.
*
* TODO: Complete functionality once API is available.
*/
@Component({
selector: 'mifosx-users',
templateUrl: './users.component.html',
@@ -19,33 +22,60 @@ export interface User {
})
export class UsersComponent implements OnInit {
/** Self service users. */
userData: User[];
/** Columns to be displayed in users table. */
displayedColumns: string[] = ['select', 'name', 'id', 'email', 'status', 'officeName', 'staff'];
dataSource: any;
/** Data source for users table. */
dataSource: MatTableDataSource<User>;
/** Selection model for users table. */
selection = new SelectionModel<User>(true, []);
/** Paginator for users table. */
@ViewChild(MatPaginator) paginator: MatPaginator;
/** Sorter for users table. */
@ViewChild(MatSort) sort: MatSort;
constructor(private userService: UserService) { }
ngOnInit() {
this.userService.getUsers().subscribe((data: User[]) => {
this.dataSource = new MatTableDataSource(data);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
/**
* Retrieves the users data from `resolve`.
* @param {ActivatedRoute} route Activated Route.
*/
constructor(private route: ActivatedRoute) {
this.route.data.subscribe((data: { users: User[] }) => {
this.userData = data.users;
});
}
/**
* Initializes the data source, paginator and sorter for users table.
*/
ngOnInit() {
this.dataSource = new MatTableDataSource(this.userData);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
/**
* Filters data in users table based on passed value.
* @param {string} filterValue Value to filter data.
*/
applyFilter(filterValue: string) {
this.dataSource.filter = filterValue.trim().toLowerCase();
}
isAllSelected() {
/**
* Checks if all rows of users table are selected.
* @returns {boolean} True if all rows are selected.
*/
isAllSelected(): boolean {
const numSelected = this.selection.selected.length;
const numRows = this.dataSource.data.length;
return numSelected === numRows;
}
/**
* Toggles selection for all rows of users table.
*/
masterToggle() {
this.isAllSelected() ?
this.selection.clear() :
@@ -0,0 +1,33 @@
/** Angular Routes */
import { Injectable } from '@angular/core';
import { Resolve } from '@angular/router';
/** rxjs Imports */
import { Observable } from 'rxjs';
/** Custom Services */
import { UserService } from './user.service';
/** Custom Model */
import { User } from './user.model';
/**
* Self service users data resolver.
*/
@Injectable()
export class UsersResolver implements Resolve<Object> {
/**
* @param {UserService} userService Self service user service.
*/
constructor(private userService: UserService) {}
/**
* Returns the users data.
* @returns {Observable<User[]>}
*/
resolve(): Observable<User[]> {
return this.userService.getUsers();
}
}
@@ -1,102 +1,120 @@
<mat-card class="container m-t-40">
<div class="container m-b-20" fxLayout="row" fxLayout.lt-md="column" fxLayoutAlign="end" fxLayoutGap="2%">
<!-- TODO: Update to show only Activate/Inactivate button at a time according to status of user. -->
<button mat-raised-button color="accent">
<fa-icon icon="lock-open"></fa-icon>&nbsp;&nbsp;
Activate
</button>
<button mat-raised-button color="warn">
<fa-icon icon="lock"></fa-icon>&nbsp;&nbsp;
Deactivate
</button>
<button mat-raised-button color="primary" (click)="openDialog()">
<fa-icon icon="cog"></fa-icon>&nbsp;&nbsp;
Change Password
</button>
<button mat-raised-button color="primary" [routerLink]="['edit']">
<fa-icon icon="edit"></fa-icon>&nbsp;&nbsp;
Edit
</button>
</div>
<mat-card-header>
<mat-icon matTooltip="Status" matTooltipPosition="above">lens</mat-icon>&nbsp;&nbsp;User ID: 123456
</mat-card-header>
<div class="container">
<mat-card-actions align="right">
<button mat-raised-button color="primary" [routerLink]="['/self-service/users/view/123456/edit']"><mat-icon>edit</mat-icon>&nbsp;&nbsp;Edit</button>
<button mat-raised-button color="primary" (click)="openDialog()"><mat-icon>settings</mat-icon>&nbsp;&nbsp;Change Password</button>
<button mat-raised-button color="primary"><mat-icon>lock</mat-icon>&nbsp;&nbsp;Deactivate</button>
</mat-card-actions>
<mat-card>
<mat-card-content>
<mat-card-content>
<mat-grid-list cols="2" rowHeight="40px" style="width: 600px;">
<div fxLayout="row wrap" class="content">
<mat-grid-tile>
Username
</mat-grid-tile>
<div fxFlex="100%" class="header">
<fa-icon icon="circle" size="lg" matTooltip="{{ user.status }}" matTooltipPosition="above"></fa-icon>&nbsp;&nbsp;
ID: {{ user.id }}
</div>
<mat-grid-tile>
abhaychawla
</mat-grid-tile>
<div fxFlex="50%" class="header">
Username
</div>
<mat-grid-tile>
First Name
</mat-grid-tile>
<div fxFlex="50%">
{{ user.username }}
</div>
<mat-grid-tile>
Abhay
</mat-grid-tile>
<div fxFlex="50%" class="header">
First Name
</div>
<mat-grid-tile>
Last Name
</mat-grid-tile>
<div fxFlex="50%">
{{ user.firstName }}
</div>
<mat-grid-tile>
Chawla
</mat-grid-tile>
<div fxFlex="50%" class="header">
Last Name
</div>
<mat-grid-tile>
Gender
</mat-grid-tile>
<div fxFlex="50%">
{{ user.lastName }}
</div>
<mat-grid-tile>
Male
</mat-grid-tile>
<div fxFlex="50%" class="header">
Gender
</div>
<mat-grid-tile>
Date of Birth
</mat-grid-tile>
<div fxFlex="50%">
{{ user.gender }}
</div>
<mat-grid-tile>
18/06/1997
</mat-grid-tile>
<div fxFlex="50%" class="header">
Date of Birth
</div>
<mat-grid-tile>
Email
</mat-grid-tile>
<div fxFlex="50%">
{{ user.dateOfBirth }}
</div>
<mat-grid-tile>
abhay.chawla97@gmail.com
</mat-grid-tile>
<div fxFlex="50%" class="header">
Email
</div>
<mat-grid-tile>
Mobile
</mat-grid-tile>
<div fxFlex="50%">
{{ user.email }}
</div>
<mat-grid-tile>
9871105236
</mat-grid-tile>
<div fxFlex="50%" class="header">
Mobile
</div>
<mat-grid-tile>
Office
</mat-grid-tile>
<div fxFlex="50%">
{{ user.mobile }}
</div>
<mat-grid-tile>
Head Office
</mat-grid-tile>
<div fxFlex="50%" class="header">
Office
</div>
<div fxFlex="50%">
{{ user.office }}
</div>
<mat-grid-tile>
Staff
</mat-grid-tile>
<div fxFlex="50%" class="header">
Staff
</div>
<mat-grid-tile>
Smith W
</mat-grid-tile>
<div fxFlex="50%">
{{ user.staff }}
</div>
<mat-grid-tile>
Activation Date
</mat-grid-tile>
<div fxFlex="50%" class="header">
Activation Date
</div>
<mat-grid-tile>
12/03/2018
</mat-grid-tile>
<div fxFlex="50%">
{{ user.activationDate }}
</div>
</mat-grid-list>
</div>
</mat-card-content>
</mat-card-content>
</mat-card>
</mat-card>
</div>
@@ -0,0 +1,14 @@
.container {
max-width: 37rem;
.content {
div {
margin: 1rem 0;
word-wrap: break-word;
}
.header {
font-weight: 500;
}
}
}
@@ -1,5 +1,12 @@
/** Angular Imports */
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
/**
* View self service user component.
*
* TODO: Complete functionality once API is available.
*/
@Component({
selector: 'mifosx-view-user',
templateUrl: './view-user.component.html',
@@ -7,13 +14,24 @@ import { Component, OnInit } from '@angular/core';
})
export class ViewUserComponent implements OnInit {
constructor() { }
/** Self service user. */
user: any;
/**
* Retrieves the user data from `resolve`.
* @param {ActivatedRoute} route Activated Route.
*/
constructor(private route: ActivatedRoute) {
this.route.data.subscribe((data: { user: any }) => {
this.user = data.user;
});
}
ngOnInit() {
}
openDialog() {
// TODO: Change Password Dialog
// TODO: Open change password dialog.
}
}
@@ -1,15 +1,32 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { Resolve } from '@angular/router';
import { Observable, of } from 'rxjs';
/** rxjs Imports */
import { Observable } from 'rxjs';
/** Custom Services */
import { UserService } from '../user.service';
/** Custom Model */
import { User } from '../user.model';
/**
* View self service user data resolver.
*/
@Injectable()
export class ViewUserResolver implements Resolve<Object> {
/**
* @param {UserService} userService Self service user service.
*/
constructor(private userService: UserService) {}
resolve(): Observable<any> {
/**
* Returns the user data.
* @returns {Observable<User>}
*/
resolve(): Observable<User> {
return this.userService.getUser();
}
+6
View File
@@ -11,7 +11,9 @@ import {
faCheckCircle,
faChevronLeft,
faChevronRight,
faCircle,
faCog,
faEdit,
faEye,
faEyeSlash,
faFileUpload,
@@ -19,6 +21,7 @@ import {
faHome,
faLocationArrow,
faLock,
faLockOpen,
faMoneyBillAlt,
faPlus,
faSearch,
@@ -41,7 +44,9 @@ library.add(
faCheckCircle,
faChevronLeft,
faChevronRight,
faCircle,
faCog,
faEdit,
faEye,
faEyeSlash,
faFileUpload,
@@ -49,6 +54,7 @@ library.add(
faHome,
faLocationArrow,
faLock,
faLockOpen,
faMoneyBillAlt,
faPlus,
faSearch,
+12 -2
View File
@@ -1,4 +1,14 @@
{
"id": 1,
"username": "abhaychawla"
"id": 1600,
"username": "abhaychawla",
"status": "status",
"firstName": "Abhay",
"lastName": "Chawla",
"gender": "Male",
"dateOfBirth": "18/06/1997",
"email": "abhay.chawla97@gmail.com",
"mobile": "9871105236",
"office": "Head Office",
"staff": "Smith W",
"activationDate": "12/03/2018"
}