Compare commits
30 Commits
main
...
mazdak/UX-
| Author | SHA1 | Date |
|---|---|---|
|
|
a6a38d068e | 1 day ago |
|
|
c257ed7e6f | 2 days ago |
|
|
f7be4f6c7b | 3 days ago |
|
|
7dacf6f9c8 | 3 days ago |
|
|
0cc25afccd | 3 days ago |
|
|
3c3f1b5ee0 | 3 days ago |
|
|
b0f8311a2c | 3 days ago |
|
|
7228790cc8 | 3 days ago |
|
|
83dc8b5c7f | 3 days ago |
|
|
ebde11ad65 | 3 days ago |
|
|
e1ec631421 | 4 days ago |
|
|
bf3fe98e63 | 4 days ago |
|
|
cda611495b | 4 days ago |
|
|
c4ccfaf24a | 4 days ago |
|
|
6d88ae8767 | 4 days ago |
|
|
88ffd7a35b | 4 days ago |
|
|
084d17e6ad | 1 week ago |
|
|
71c767c684 | 1 week ago |
|
|
d0f3d28458 | 1 week ago |
|
|
bf3df61c9d | 1 week ago |
|
|
65aded50be | 1 week ago |
|
|
9ee1c0f4e2 | 1 week ago |
|
|
b6fe4e0398 | 1 week ago |
|
|
5e38a86049 | 1 week ago |
|
|
36904b68fd | 1 week ago |
|
|
8eaf5948ab | 1 week ago |
|
|
edfea86870 | 1 week ago |
|
|
3fbe09a4ee | 1 week ago |
|
|
383772db87 | 1 week ago |
|
|
d59d64987c | 2 weeks ago |
@ -0,0 +1,17 @@
|
|||||||
|
# Editor configuration, see https://editorconfig.org
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.ts]
|
||||||
|
quote_type = single
|
||||||
|
ij_typescript_use_double_quotes = false
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
max_line_length = off
|
||||||
|
trim_trailing_whitespace = false
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
# See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files.
|
||||||
|
package-lock.json
|
||||||
|
|
||||||
|
# Compiled output
|
||||||
|
/dist
|
||||||
|
/tmp
|
||||||
|
/out-tsc
|
||||||
|
/bazel-out
|
||||||
|
|
||||||
|
# Node
|
||||||
|
/node_modules
|
||||||
|
npm-debug.log
|
||||||
|
yarn-error.log
|
||||||
|
|
||||||
|
# IDEs and editors
|
||||||
|
.idea/
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.c9/
|
||||||
|
*.launch
|
||||||
|
.settings/
|
||||||
|
*.sublime-workspace
|
||||||
|
|
||||||
|
# Visual Studio Code
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.history/*
|
||||||
|
|
||||||
|
# Miscellaneous
|
||||||
|
/.angular/cache
|
||||||
|
.sass-cache/
|
||||||
|
/connect.lock
|
||||||
|
/coverage
|
||||||
|
/libpeerconnection.log
|
||||||
|
testem.log
|
||||||
|
/typings
|
||||||
|
|
||||||
|
# System files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
|
||||||
|
"recommendations": ["angular.ng-template"]
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "ng serve",
|
||||||
|
"type": "chrome",
|
||||||
|
"request": "launch",
|
||||||
|
"preLaunchTask": "npm: start",
|
||||||
|
"url": "http://localhost:4200/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ng test",
|
||||||
|
"type": "chrome",
|
||||||
|
"request": "launch",
|
||||||
|
"preLaunchTask": "npm: test",
|
||||||
|
"url": "http://localhost:9876/debug.html"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"type": "npm",
|
||||||
|
"script": "start",
|
||||||
|
"isBackground": true,
|
||||||
|
"problemMatcher": {
|
||||||
|
"owner": "typescript",
|
||||||
|
"pattern": "$tsc",
|
||||||
|
"background": {
|
||||||
|
"activeOnStart": true,
|
||||||
|
"beginsPattern": {
|
||||||
|
"regexp": "(.*?)"
|
||||||
|
},
|
||||||
|
"endsPattern": {
|
||||||
|
"regexp": "bundle generation complete"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "npm",
|
||||||
|
"script": "test",
|
||||||
|
"isBackground": true,
|
||||||
|
"problemMatcher": {
|
||||||
|
"owner": "typescript",
|
||||||
|
"pattern": "$tsc",
|
||||||
|
"background": {
|
||||||
|
"activeOnStart": true,
|
||||||
|
"beginsPattern": {
|
||||||
|
"regexp": "(.*?)"
|
||||||
|
},
|
||||||
|
"endsPattern": {
|
||||||
|
"regexp": "bundle generation complete"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -0,0 +1,59 @@
|
|||||||
|
# ACONNECTUX
|
||||||
|
|
||||||
|
This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 19.2.19.
|
||||||
|
|
||||||
|
## Development server
|
||||||
|
|
||||||
|
To start a local development server, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ng serve
|
||||||
|
```
|
||||||
|
|
||||||
|
Once the server is running, open your browser and navigate to `http://localhost:4200/`. The application will automatically reload whenever you modify any of the source files.
|
||||||
|
|
||||||
|
## Code scaffolding
|
||||||
|
|
||||||
|
Angular CLI includes powerful code scaffolding tools. To generate a new component, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ng generate component component-name
|
||||||
|
```
|
||||||
|
|
||||||
|
For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ng generate --help
|
||||||
|
```
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
To build the project run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ng build
|
||||||
|
```
|
||||||
|
|
||||||
|
This will compile your project and store the build artifacts in the `dist/` directory. By default, the production build optimizes your application for performance and speed.
|
||||||
|
|
||||||
|
## Running unit tests
|
||||||
|
|
||||||
|
To execute unit tests with the [Karma](https://karma-runner.github.io) test runner, use the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ng test
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running end-to-end tests
|
||||||
|
|
||||||
|
For end-to-end (e2e) testing, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ng e2e
|
||||||
|
```
|
||||||
|
|
||||||
|
Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.
|
||||||
|
|
||||||
|
## Additional Resources
|
||||||
|
|
||||||
|
For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
|
||||||
@ -0,0 +1,117 @@
|
|||||||
|
{
|
||||||
|
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||||
|
"version": 1,
|
||||||
|
"newProjectRoot": "projects",
|
||||||
|
"projects": {
|
||||||
|
"ACONNECT-UX": {
|
||||||
|
"projectType": "application",
|
||||||
|
"schematics": {
|
||||||
|
"@schematics/angular:component": {
|
||||||
|
"style": "scss"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "",
|
||||||
|
"sourceRoot": "src",
|
||||||
|
"prefix": "app",
|
||||||
|
"architect": {
|
||||||
|
"build": {
|
||||||
|
"builder": "@angular-devkit/build-angular:application",
|
||||||
|
"options": {
|
||||||
|
"outputPath": "dist/aconnect-ux",
|
||||||
|
"index": "src/index.html",
|
||||||
|
"browser": "src/main.ts",
|
||||||
|
"polyfills": [
|
||||||
|
"zone.js"
|
||||||
|
],
|
||||||
|
"tsConfig": "tsconfig.app.json",
|
||||||
|
"inlineStyleLanguage": "scss",
|
||||||
|
"assets": [
|
||||||
|
"src/favicon.ico",
|
||||||
|
"src/assets"
|
||||||
|
],
|
||||||
|
"styles": [
|
||||||
|
"src/styles.scss",
|
||||||
|
"node_modules/@ng-select/ng-select/themes/default.theme.css",
|
||||||
|
"node_modules/ngx-toastr/toastr.css",
|
||||||
|
"src/assets/css/owl.carousel.min.css",
|
||||||
|
"src/assets/css/bootstrap.min.css",
|
||||||
|
"src/assets/css/icons.min.css",
|
||||||
|
"src/assets/css/app.min.css"
|
||||||
|
],
|
||||||
|
"scripts": [],
|
||||||
|
"server": "src/main.server.ts",
|
||||||
|
"outputMode": "server",
|
||||||
|
"ssr": {
|
||||||
|
"entry": "src/server.ts"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"budgets": [
|
||||||
|
{
|
||||||
|
"type": "initial",
|
||||||
|
"maximumWarning": "500kB",
|
||||||
|
"maximumError": "1MB"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "anyComponentStyle",
|
||||||
|
"maximumWarning": "4kB",
|
||||||
|
"maximumError": "8kB"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"outputHashing": "all",
|
||||||
|
"fileReplacements": [
|
||||||
|
{
|
||||||
|
"replace": "src/environments/environment.ts",
|
||||||
|
"with": "src/environments/environment.prod.ts"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"development": {
|
||||||
|
"optimization": false,
|
||||||
|
"extractLicenses": false,
|
||||||
|
"sourceMap": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultConfiguration": "production"
|
||||||
|
},
|
||||||
|
"serve": {
|
||||||
|
"builder": "@angular-devkit/build-angular:dev-server",
|
||||||
|
"configurations": {
|
||||||
|
"production": {
|
||||||
|
"buildTarget": "ACONNECT-UX:build:production"
|
||||||
|
},
|
||||||
|
"development": {
|
||||||
|
"buildTarget": "ACONNECT-UX:build:development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"defaultConfiguration": "development"
|
||||||
|
},
|
||||||
|
"extract-i18n": {
|
||||||
|
"builder": "@angular-devkit/build-angular:extract-i18n"
|
||||||
|
},
|
||||||
|
"test": {
|
||||||
|
"builder": "@angular-devkit/build-angular:karma",
|
||||||
|
"options": {
|
||||||
|
"polyfills": [
|
||||||
|
"zone.js",
|
||||||
|
"zone.js/testing"
|
||||||
|
],
|
||||||
|
"tsConfig": "tsconfig.spec.json",
|
||||||
|
"inlineStyleLanguage": "scss",
|
||||||
|
"assets": [
|
||||||
|
{
|
||||||
|
"glob": "**/*",
|
||||||
|
"input": "public"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"styles": [
|
||||||
|
"src/styles.scss"
|
||||||
|
],
|
||||||
|
"scripts": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"name": "aconnect-ux",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"scripts": {
|
||||||
|
"ng": "ng",
|
||||||
|
"start": "ng serve",
|
||||||
|
"build": "ng build",
|
||||||
|
"build:prod": "ng build --configuration=production",
|
||||||
|
"watch": "ng build --watch --configuration development",
|
||||||
|
"test": "ng test",
|
||||||
|
"serve:ssr:ACONNECT-UX": "node dist/aconnect-ux/server/server.mjs"
|
||||||
|
},
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@angular/animations": "^19.1.0",
|
||||||
|
"@angular/cdk": "^19.1.0",
|
||||||
|
"@angular/common": "^19.1.0",
|
||||||
|
"@angular/compiler": "^19.1.0",
|
||||||
|
"@angular/core": "^19.1.0",
|
||||||
|
"@angular/forms": "^19.1.0",
|
||||||
|
"@angular/platform-browser": "^19.1.0",
|
||||||
|
"@angular/platform-browser-dynamic": "^19.1.0",
|
||||||
|
"@angular/platform-server": "^19.1.0",
|
||||||
|
"@angular/router": "^19.1.0",
|
||||||
|
"@angular/ssr": "^19.1.6",
|
||||||
|
"@ng-select/ng-select": "^14.8.0",
|
||||||
|
"@ngx-translate/core": "^17.0.0",
|
||||||
|
"@ngx-translate/http-loader": "^16.0.1",
|
||||||
|
"bootstrap": "^5.3.8",
|
||||||
|
"express": "^4.18.2",
|
||||||
|
"ngx-spinner": "^19.0.0",
|
||||||
|
"ngx-toastr": "^19.1.0",
|
||||||
|
"rxjs": "~7.8.0",
|
||||||
|
"tslib": "^2.3.0",
|
||||||
|
"zone.js": "~0.15.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@angular-devkit/build-angular": "^19.1.0",
|
||||||
|
"@angular/cli": "^19.1.0",
|
||||||
|
"@angular/compiler-cli": "^19.1.0",
|
||||||
|
"@types/express": "^4.17.17",
|
||||||
|
"@types/jasmine": "~5.1.0",
|
||||||
|
"@types/node": "^18.18.0",
|
||||||
|
"jasmine-core": "~5.5.0",
|
||||||
|
"karma": "~6.4.0",
|
||||||
|
"karma-chrome-launcher": "~3.2.0",
|
||||||
|
"karma-coverage": "~2.2.0",
|
||||||
|
"karma-jasmine": "~5.1.0",
|
||||||
|
"karma-jasmine-html-reporter": "~2.1.0",
|
||||||
|
"typescript": "~5.7.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
@ -0,0 +1,2 @@
|
|||||||
|
<app-loader></app-loader>
|
||||||
|
<router-outlet></router-outlet>
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
|
describe('AppComponent', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [AppComponent],
|
||||||
|
}).compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create the app', () => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
const app = fixture.componentInstance;
|
||||||
|
expect(app).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should have the 'ACONNECT-UX' title`, () => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
const app = fixture.componentInstance;
|
||||||
|
expect(app.title).toEqual('ACONNECT-UX');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render title', () => {
|
||||||
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
|
const compiled = fixture.nativeElement as HTMLElement;
|
||||||
|
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, ACONNECT-UX');
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
import { Component, Inject, PLATFORM_ID } from '@angular/core';
|
||||||
|
import { RouterOutlet } from '@angular/router';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { StorageService } from './shared/services/storage.service';
|
||||||
|
import { isPlatformBrowser } from '@angular/common';
|
||||||
|
import { directions, supportedLanguages } from './utils/enums';
|
||||||
|
import { LoaderComponent } from './shared/components/loader/loader.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-root',
|
||||||
|
imports: [RouterOutlet, LoaderComponent],
|
||||||
|
templateUrl: './app.component.html',
|
||||||
|
styleUrl: './app.component.scss'
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
direction: any;
|
||||||
|
title = 'ACONNECT-UX';
|
||||||
|
|
||||||
|
constructor(private translateService: TranslateService, private storageService: StorageService,
|
||||||
|
@Inject(PLATFORM_ID) private platformId: object
|
||||||
|
) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
if (this.storageService.getItem('language')) {
|
||||||
|
const currentLanguage = this.storageService.getItem('language')!;
|
||||||
|
if (isPlatformBrowser(this.platformId)) {
|
||||||
|
this.translateService.setDefaultLang(currentLanguage);
|
||||||
|
this.translateService.use(currentLanguage);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.direction = this.storageService.getItem('direction');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (isPlatformBrowser(this.platformId)) {
|
||||||
|
this.translateService.setDefaultLang('English');
|
||||||
|
this.translateService.use('English');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.storageService.setItem('language', supportedLanguages.ENGLISH);
|
||||||
|
this.direction = directions.LTR;
|
||||||
|
this.storageService.setItem('direction', this.direction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
import { mergeApplicationConfig, ApplicationConfig } from '@angular/core';
|
||||||
|
import { provideServerRendering } from '@angular/platform-server';
|
||||||
|
import { provideServerRouting } from '@angular/ssr';
|
||||||
|
import { appConfig } from './app.config';
|
||||||
|
import { serverRoutes } from './app.routes.server';
|
||||||
|
|
||||||
|
const serverConfig: ApplicationConfig = {
|
||||||
|
providers: [
|
||||||
|
provideServerRendering(),
|
||||||
|
provideServerRouting(serverRoutes)
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
export const config = mergeApplicationConfig(appConfig, serverConfig);
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
import { ApplicationConfig, importProvidersFrom, provideZoneChangeDetection } from '@angular/core';
|
||||||
|
import { provideRouter } from '@angular/router';
|
||||||
|
|
||||||
|
import { routes } from './app.routes';
|
||||||
|
import { provideClientHydration, withEventReplay } from '@angular/platform-browser';
|
||||||
|
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { HTTP_INTERCEPTORS, HttpClient, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
|
||||||
|
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
|
||||||
|
import { AuthInterceptor } from './shared/interceptors/auth.interceptor';
|
||||||
|
import { ToastrModule } from 'ngx-toastr';
|
||||||
|
import { provideAnimations } from '@angular/platform-browser/animations';
|
||||||
|
import { LoadingInterceptor } from './shared/interceptors/loading.interceptor';
|
||||||
|
|
||||||
|
export function HttpLoaderFactory(http: HttpClient) {
|
||||||
|
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
|
||||||
|
}
|
||||||
|
|
||||||
|
export const appConfig: ApplicationConfig = {
|
||||||
|
providers: [
|
||||||
|
provideZoneChangeDetection({ eventCoalescing: true }),
|
||||||
|
provideRouter(routes),
|
||||||
|
provideClientHydration(withEventReplay()),
|
||||||
|
provideHttpClient(withInterceptorsFromDi()),
|
||||||
|
provideAnimations(),
|
||||||
|
{
|
||||||
|
provide: HTTP_INTERCEPTORS,
|
||||||
|
useClass: AuthInterceptor,
|
||||||
|
multi: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: HTTP_INTERCEPTORS,
|
||||||
|
useClass: LoadingInterceptor,
|
||||||
|
multi: true
|
||||||
|
},
|
||||||
|
importProvidersFrom(
|
||||||
|
TranslateModule.forRoot({
|
||||||
|
loader: {
|
||||||
|
provide: TranslateLoader,
|
||||||
|
useFactory: HttpLoaderFactory,
|
||||||
|
deps: [HttpClient],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
ToastrModule.forRoot({
|
||||||
|
timeOut: 4000,
|
||||||
|
positionClass: 'toast-top-right',
|
||||||
|
newestOnTop: true,
|
||||||
|
closeButton: true
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
};
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
import { RenderMode, ServerRoute } from '@angular/ssr';
|
||||||
|
|
||||||
|
export const serverRoutes: ServerRoute[] = [
|
||||||
|
{
|
||||||
|
path: '**',
|
||||||
|
renderMode: RenderMode.Prerender
|
||||||
|
}
|
||||||
|
];
|
||||||
@ -0,0 +1,128 @@
|
|||||||
|
import { Routes } from '@angular/router';
|
||||||
|
import { LoginComponent } from './authenticate/login/login.component';
|
||||||
|
import { ChangePasswordComponent } from './user-management/change-password/change-password.component';
|
||||||
|
import { FullLayoutComponent } from './full-layout/full-layout.component';
|
||||||
|
import { GAuth } from './shared/guards/gauth.guard';
|
||||||
|
|
||||||
|
export const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: 'login',
|
||||||
|
component: LoginComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'changepassword',
|
||||||
|
component: ChangePasswordComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
redirectTo: 'login',
|
||||||
|
pathMatch: 'full'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'home',
|
||||||
|
component: FullLayoutComponent,
|
||||||
|
canActivate: [GAuth],
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
redirectTo: 'dashboard',
|
||||||
|
pathMatch: 'full'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'dashboard',
|
||||||
|
loadComponent: () =>
|
||||||
|
import('./dashboard/dashboard.component').then(
|
||||||
|
m => m.DashboardComponent
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'permissions',
|
||||||
|
loadComponent: () =>
|
||||||
|
import('./user-permissions/user-permissions.component').then(
|
||||||
|
m => m.UserPermissionsComponent
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'smsLogger',
|
||||||
|
loadComponent: () =>
|
||||||
|
import('./sms-banking/sms-banking.component').then(
|
||||||
|
m => m.SmsBankingComponent
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'smsGateway',
|
||||||
|
loadComponent: () =>
|
||||||
|
import('./sms-gateway/sms-gateway.component').then(
|
||||||
|
m => m.SmsGatewayComponent
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'loggerManager',
|
||||||
|
loadComponent: () =>
|
||||||
|
import('./logging/logging.component').then(
|
||||||
|
m => m.LoggingComponent
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'analysis',
|
||||||
|
loadComponent: () =>
|
||||||
|
import('./data-analysis/data-analysis.component').then(
|
||||||
|
m => m.DataAnalysisComponent
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'ibUnblockUser',
|
||||||
|
loadComponent: () =>
|
||||||
|
import('./ib-support/ib-unblock-user/ib-unblock-user.component').then(
|
||||||
|
m => m.IbUnblockUserComponent
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'feedbackSetup',
|
||||||
|
loadComponent: () =>
|
||||||
|
import('./ib-support/feedback-setup/feedback-setup.component').then(
|
||||||
|
m => m.FeedbackSetupComponent
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'purposeSetup',
|
||||||
|
loadComponent: () =>
|
||||||
|
import('./ib-support/tran-purpose-setup/tran-purpose-setup.component').then(
|
||||||
|
m => m.TranPurposeSetupComponent
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'thirdPartyRegistration',
|
||||||
|
loadComponent: () =>
|
||||||
|
import('./user-management/third-party-registration/third-party-registration.component').then(
|
||||||
|
m => m.ThirdPartyRegistrationComponent
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'setupUser',
|
||||||
|
loadComponent: () =>
|
||||||
|
import('./user-management/setup-user/setup-user.component').then(
|
||||||
|
m => m.SetupUserComponent
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'resetPassword',
|
||||||
|
loadComponent: () =>
|
||||||
|
import('./user-management/reset-password/reset-password.component').then(
|
||||||
|
m => m.ResetPasswordComponent
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'changePassword',
|
||||||
|
loadComponent: () =>
|
||||||
|
import('./user-management/change-password/change-password.component').then(
|
||||||
|
m => m.ChangePasswordComponent
|
||||||
|
)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '**',
|
||||||
|
redirectTo: 'home/dashboard'
|
||||||
|
}
|
||||||
|
];
|
||||||
@ -0,0 +1,64 @@
|
|||||||
|
<div>
|
||||||
|
<div class="col-md-11 mx-auto">
|
||||||
|
<div class="row">
|
||||||
|
<div class="page-title-box d-sm-flex align-items-center pt-2 justify-content-between sticky-top">
|
||||||
|
<div class="col-xl-11"></div>
|
||||||
|
<div class="col-xl-1 mt-2">
|
||||||
|
<div class="page-title-right float-end mx-3">
|
||||||
|
<select class="form-select" [formControl]="currentLanguage" (change)="onLangChange()" style="width: 100px;">
|
||||||
|
<option [value]="supportedLanguages.ENGLISH">{{"english" | translate}}</option>
|
||||||
|
<option [value]="supportedLanguages.ARABIC">{{"arabic" | translate}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="auth-page d-flex align-items-center">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-8 col-lg-6 col-xl-3-4">
|
||||||
|
<div class="card">
|
||||||
|
<div class="bg-primary bg-soft text-center py-3 mt-2">
|
||||||
|
<img src="assets/images/logo.png" class="img-fluid mb-2" height="120" width="150" alt="Logo">
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form [formGroup]="loginForm" class="form-horizontal">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="USER_ID" class="form-label">{{"userName" | translate}}</label>
|
||||||
|
<div class="input-group auth-pass-inputgroup">
|
||||||
|
<input type="text" class="form-control" id="USER_ID" formControlName="USER_ID">
|
||||||
|
</div>
|
||||||
|
<div *ngIf="loginForm.get('USER_ID')?.invalid && loginForm.get('USER_ID')?.touched" class="text-danger">
|
||||||
|
<small *ngIf="loginForm.get('USER_ID')?.errors?.['required']">{{"userNameRequired" | translate}}</small>
|
||||||
|
<small *ngIf="loginForm.get('USER_ID')?.errors?.['pattern']">{{"userNamePattterenError" | translate}}</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="PASSWORD" class="form-label">{{"password" | translate}}</label>
|
||||||
|
<div class="input-group auth-pass-inputgroup">
|
||||||
|
<input type="{{passwordType}}" class="form-control" id="PASSWORD" formControlName="PASSWORD" aria-label="Password" autocomplete="current-password">
|
||||||
|
<app-password-hide-show [showPassword]="true" (onEyeClick)="togglePasswordType()"></app-password-hide-show>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="loginForm.get('PASSWORD')?.invalid && loginForm.get('PASSWORD')?.touched" class="text-danger">
|
||||||
|
<small *ngIf="loginForm.get('PASSWORD')?.errors?.['required']">{{"PasswordRequired" | translate}}</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3 d-grid">
|
||||||
|
<button class="btn btn-primary waves-effect waves-light" type="submit" (click)="login()" [disabled]="loginForm.invalid">{{"login" | translate}}</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row fixed-bottom">
|
||||||
|
<div class="col-md-12 float-left">
|
||||||
|
<p class="Copyright-text"><span class="VersionNumber">{{ versionNumber }} {{ buildDate }}</span></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
@media (max-width: 768px) {
|
||||||
|
.VersionNumber{
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { LoginComponent } from './login.component';
|
||||||
|
|
||||||
|
describe('LoginComponent', () => {
|
||||||
|
let component: LoginComponent;
|
||||||
|
let fixture: ComponentFixture<LoginComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [LoginComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(LoginComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,133 @@
|
|||||||
|
import { Component, Inject, inject, PLATFORM_ID, ViewChild } from '@angular/core';
|
||||||
|
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
||||||
|
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||||
|
|
||||||
|
import { CONSTANTS } from '../../utils/app.constants';
|
||||||
|
import { PasswordHideShowComponent } from '../../shared/components/password-hide-show/password-hide-show.component';
|
||||||
|
import { AuthService } from '../../services/auth.service';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { MiscService } from '../../shared/services/misc.service';
|
||||||
|
import { User } from '../../models/user';
|
||||||
|
import { CommonModule, isPlatformBrowser } from '@angular/common';
|
||||||
|
import { StorageService } from '../../shared/services/storage.service';
|
||||||
|
import { directions, supportedLanguages } from '../../utils/enums';
|
||||||
|
import { environment } from '../../../environments/environment';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-login',
|
||||||
|
imports: [TranslateModule, ReactiveFormsModule, CommonModule, PasswordHideShowComponent],
|
||||||
|
templateUrl: './login.component.html',
|
||||||
|
styleUrl: './login.component.scss'
|
||||||
|
})
|
||||||
|
export class LoginComponent {
|
||||||
|
versionNumber: string = '';
|
||||||
|
buildDate: string = '';
|
||||||
|
buildNumber: string = '';
|
||||||
|
loginForm!: FormGroup;
|
||||||
|
currentLanguage = new FormControl();
|
||||||
|
passwordType: string = 'password';
|
||||||
|
direction: string = '';
|
||||||
|
supportedLanguages = supportedLanguages;
|
||||||
|
@ViewChild(PasswordHideShowComponent) passwordHideShow?: PasswordHideShowComponent;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private authService: AuthService,
|
||||||
|
private translateService: TranslateService,
|
||||||
|
private router: Router,
|
||||||
|
private miscService: MiscService,
|
||||||
|
private storageService: StorageService,
|
||||||
|
@Inject(PLATFORM_ID) private platformId: object
|
||||||
|
) {
|
||||||
|
this.initializeLanguage();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.initializeLoginForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
setVersionNumberAndBuildDate(){
|
||||||
|
this.translateService.get('versionAndBuildNumber', {
|
||||||
|
versionNumber: environment.versionNumber,
|
||||||
|
buildNumber: environment.buildNumber
|
||||||
|
}).subscribe((res: string) => {
|
||||||
|
this.versionNumber = res;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.translateService.get('versionBuildDate', {
|
||||||
|
date: environment.buildDate
|
||||||
|
}).subscribe((res: string) => {
|
||||||
|
this.buildDate = res;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
initializeLanguage(): void {
|
||||||
|
if (isPlatformBrowser(this.platformId)) {
|
||||||
|
const savedLanguage = this.storageService.getItem('language') || 'English';
|
||||||
|
this.storageService.setItem('language', savedLanguage);
|
||||||
|
this.currentLanguage.setValue(savedLanguage)
|
||||||
|
this.translateService.setDefaultLang(savedLanguage);
|
||||||
|
this.translateService.use(savedLanguage).subscribe(() => {
|
||||||
|
this.setVersionNumberAndBuildDate();
|
||||||
|
});
|
||||||
|
this.setDirection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setDirection() {
|
||||||
|
let selectedLang = this.currentLanguage.value;
|
||||||
|
if (selectedLang === supportedLanguages.ENGLISH) {
|
||||||
|
this.direction = directions.LTR;
|
||||||
|
this.storageService.setItem('direction', this.direction);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.direction = directions.RTL;
|
||||||
|
this.storageService.setItem('direction', this.direction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
initializeLoginForm() {
|
||||||
|
this.loginForm = new FormGroup({
|
||||||
|
USER_ID: new FormControl('', [Validators.required, Validators.pattern('^[a-z0-9]*$')]),
|
||||||
|
PASSWORD: new FormControl('', [Validators.required])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async login() {
|
||||||
|
let User: User = {
|
||||||
|
Username: this.loginForm.get("USER_ID")?.value,
|
||||||
|
Password: this.loginForm.get("PASSWORD")?.value
|
||||||
|
}
|
||||||
|
let response = await this.authService.login(User);
|
||||||
|
if ((await response["errorMessage"] == undefined)) {
|
||||||
|
if (await response) {
|
||||||
|
if (!this.authService.firstLogin) {
|
||||||
|
this.router.navigate(['home/dashboard']);
|
||||||
|
this.miscService.handleSuccess(this.translateService.instant('loginSuccess'));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.router.navigate(['home/changepassword']);
|
||||||
|
this.miscService.handleSuccess(this.translateService.instant('changePassword'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.miscService.handleError(await response["errorMessage"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onLangChange() {
|
||||||
|
const selectedLang = this.currentLanguage.value;
|
||||||
|
this.translateService.setDefaultLang(selectedLang);
|
||||||
|
this.translateService.use(selectedLang).subscribe(() => {
|
||||||
|
this.setVersionNumberAndBuildDate();
|
||||||
|
});
|
||||||
|
this.storageService.setItem('language', selectedLang);
|
||||||
|
this.setDirection();
|
||||||
|
// document.documentElement.setAttribute('dir', this.direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
togglePasswordType() {
|
||||||
|
this.passwordType = this.passwordHideShow?.showPassword ? 'password' : 'text';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
<p>dashboard works!</p>
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { DashboardComponent } from './dashboard.component';
|
||||||
|
|
||||||
|
describe('DashboardComponent', () => {
|
||||||
|
let component: DashboardComponent;
|
||||||
|
let fixture: ComponentFixture<DashboardComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [DashboardComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(DashboardComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-dashboard',
|
||||||
|
imports: [],
|
||||||
|
templateUrl: './dashboard.component.html',
|
||||||
|
styleUrl: './dashboard.component.scss'
|
||||||
|
})
|
||||||
|
export class DashboardComponent {
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
<p>data-analysis works!</p>
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { DataAnalysisComponent } from './data-analysis.component';
|
||||||
|
|
||||||
|
describe('DataAnalysisComponent', () => {
|
||||||
|
let component: DataAnalysisComponent;
|
||||||
|
let fixture: ComponentFixture<DataAnalysisComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [DataAnalysisComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(DataAnalysisComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-data-analysis',
|
||||||
|
imports: [],
|
||||||
|
templateUrl: './data-analysis.component.html',
|
||||||
|
styleUrl: './data-analysis.component.scss'
|
||||||
|
})
|
||||||
|
export class DataAnalysisComponent {
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
<div id="layout-wrapper" data-sidebar="dark" data-keep-enlarged="true">
|
||||||
|
<app-header></app-header>
|
||||||
|
<app-side-nav></app-side-nav>
|
||||||
|
<div class="main-content">
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
<footer class="footer" [dir]="direction">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<div class="text-sm-end d-none text-sm-center d-sm-block">
|
||||||
|
{{ footerText }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { FullLayoutComponent } from './full-layout.component';
|
||||||
|
|
||||||
|
describe('FullLayoutComponent', () => {
|
||||||
|
let component: FullLayoutComponent;
|
||||||
|
let fixture: ComponentFixture<FullLayoutComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [FullLayoutComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(FullLayoutComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { SideNavComponent } from '../shared/components/side-nav/side-nav.component';
|
||||||
|
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
||||||
|
import { RouterOutlet } from '@angular/router';
|
||||||
|
import { StorageService } from '../shared/services/storage.service';
|
||||||
|
import { HeaderComponent } from '../shared/components/header/header.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-full-layout',
|
||||||
|
imports: [SideNavComponent, RouterOutlet, HeaderComponent, TranslateModule],
|
||||||
|
templateUrl: './full-layout.component.html',
|
||||||
|
styleUrl: './full-layout.component.scss'
|
||||||
|
})
|
||||||
|
export class FullLayoutComponent {
|
||||||
|
|
||||||
|
direction: any;
|
||||||
|
footerText: string = '';
|
||||||
|
|
||||||
|
constructor(private translateService: TranslateService,
|
||||||
|
private stoargeService: StorageService
|
||||||
|
){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(){
|
||||||
|
this.translateService.setDefaultLang(this.stoargeService.getItem('language')!);
|
||||||
|
this.translateService.use(this.stoargeService.getItem('language')!);
|
||||||
|
this.direction = this.stoargeService.getItem('direction');
|
||||||
|
this.setFooterText();
|
||||||
|
}
|
||||||
|
|
||||||
|
setFooterText(){
|
||||||
|
this.footerText = this.translateService.instant('copyRightsReserved', {
|
||||||
|
currentYearLong: this.currentYearLong()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
currentYearLong(): number {
|
||||||
|
return new Date().getFullYear();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,126 @@
|
|||||||
|
<div id="layout-wrapper">
|
||||||
|
<div class="inner-pg-sp">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="d-sm-flex align-items-center justify-content-between navbar-header p-0">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="col-xl-12 mt-4">
|
||||||
|
<div class="card border">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-section">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="card-body mt-2 p-0">
|
||||||
|
<div class="card mb-0 mt-2">
|
||||||
|
<div
|
||||||
|
class="card-header font-edit-13-child d-flex justify-content-between align-items-center">
|
||||||
|
{{'credentialsTitle' | translate}}
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form>
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label for="userID" class="text-nowrap">
|
||||||
|
{{ 'Email' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="password-wrapper position-relative w-100">
|
||||||
|
<div class="d-flex flex-row align-items-stretch">
|
||||||
|
<input type="text" id="userID"
|
||||||
|
class="form-control"
|
||||||
|
|
||||||
|
placeholder="{{ 'Email' | translate }}" appNoWhitespaces
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- <div class="text-danger">
|
||||||
|
{{ 'requiredField' | translate }}
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3">
|
||||||
|
<p class="text-info h5">{{'2-stepAppPassword' | translate}}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-start gap-2">
|
||||||
|
<label for="password"
|
||||||
|
class="text-nowrap mt-2">
|
||||||
|
{{ 'password' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="password-wrapper position-relative w-100">
|
||||||
|
|
||||||
|
<input id="password" class="form-control" autocomplete="new-password" type="{{passwordType}}" maxlength="500"
|
||||||
|
placeholder="{{ 'password' | translate }}" appNoWhitespaces rows="3" />
|
||||||
|
<app-password-hide-show #psh class="password-eye align-items-stretch" [showPassword]="true"
|
||||||
|
(onEyeClick)="togglePasswordType()"></app-password-hide-show>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label for="confirmPassword" class="text-nowrap">
|
||||||
|
{{ 'confirmPassword' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="password-wrapper position-relative w-100">
|
||||||
|
<input id="confirmPassword" class="form-control" type="{{confirmPasswordType}}"
|
||||||
|
placeholder="{{ 'confirmPassword' | translate }}" appNoWhitespaces />
|
||||||
|
<app-password-hide-show #cpsh class="password-eye align-items-stretch" [showPassword]="true"
|
||||||
|
(onEyeClick)="toggleConfirmPasswordType()"></app-password-hide-show>
|
||||||
|
|
||||||
|
<!-- <div class="text-danger">
|
||||||
|
<div>
|
||||||
|
{{ 'requiredField' | translate }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ 'expiryBeforeRenewal' | translate }}
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6 ms-auto text-end">
|
||||||
|
<button
|
||||||
|
class="btn btn-primary waves-effect waves-light"
|
||||||
|
|
||||||
|
>{{'save' | translate}}</button>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { FeedbackSetupComponent } from './feedback-setup.component';
|
||||||
|
|
||||||
|
describe('FeedbackSetupComponent', () => {
|
||||||
|
let component: FeedbackSetupComponent;
|
||||||
|
let fixture: ComponentFixture<FeedbackSetupComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [FeedbackSetupComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(FeedbackSetupComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { Component, ViewChild } from '@angular/core';
|
||||||
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { PasswordHideShowComponent } from '../../shared/components/password-hide-show/password-hide-show.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-feedback-setup',
|
||||||
|
imports: [TranslateModule, ReactiveFormsModule, FormsModule, CommonModule, PasswordHideShowComponent],
|
||||||
|
templateUrl: './feedback-setup.component.html',
|
||||||
|
styleUrl: './feedback-setup.component.scss'
|
||||||
|
})
|
||||||
|
export class FeedbackSetupComponent {
|
||||||
|
@ViewChild('psh') passwordHideShow ?: PasswordHideShowComponent
|
||||||
|
@ViewChild('cpsh') confirmPasswordHideShow ?: PasswordHideShowComponent
|
||||||
|
|
||||||
|
passwordType: string = 'password';
|
||||||
|
confirmPasswordType: string = 'password';
|
||||||
|
|
||||||
|
togglePasswordType(){
|
||||||
|
this.passwordType = this.passwordHideShow?.showPassword ? 'password' : 'text';
|
||||||
|
}
|
||||||
|
toggleConfirmPasswordType(){
|
||||||
|
this.confirmPasswordType = this.confirmPasswordHideShow?.showPassword ? 'password' : 'text';
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,236 @@
|
|||||||
|
<div id="layout-wrapper">
|
||||||
|
<div class="inner-pg-sp">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="d-sm-flex align-items-center justify-content-between navbar-header p-0">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="col-xl-12 mt-4">
|
||||||
|
<div class="card border">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-section">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="card-body mt-2 p-0">
|
||||||
|
<div class="card mb-0 mt-2">
|
||||||
|
<div
|
||||||
|
class="card-header font-edit-13-child d-flex justify-content-between align-items-center">
|
||||||
|
{{'IBChildTitle' | translate}}
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form>
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label for="selectIdentValueType" class="text-nowrap">
|
||||||
|
{{ 'selectIdentValueType' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
class="password-wrapper position-relative w-100">
|
||||||
|
<div class="d-flex flex-row align-items-stretch">
|
||||||
|
<ng-select class="custom-select col-md-12 custom-select-sm ms-2 seleted-edit" [(ngModel)]="optionValue"
|
||||||
|
placeholder="{{ 'selectIdentValueType' | translate }}"
|
||||||
|
name="optionValue" [clearable]="false" [searchable]="false">
|
||||||
|
|
||||||
|
<!-- Select Type (CLICKABLE) -->
|
||||||
|
<ng-option value="select">
|
||||||
|
{{ 'selectIdentValueType' | translate }}
|
||||||
|
</ng-option>
|
||||||
|
|
||||||
|
<ng-option value="cnic">
|
||||||
|
{{ 'cnic_scnic' | translate }}
|
||||||
|
</ng-option>
|
||||||
|
|
||||||
|
<ng-option value="passport">
|
||||||
|
{{ 'passport' | translate }}
|
||||||
|
</ng-option>
|
||||||
|
|
||||||
|
<ng-option value="nicop">
|
||||||
|
{{ 'nicop' | translate }}
|
||||||
|
</ng-option>
|
||||||
|
|
||||||
|
<ng-option value="poc">
|
||||||
|
{{ 'poc' | translate }}
|
||||||
|
</ng-option>
|
||||||
|
|
||||||
|
</ng-select>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- <div class="text-danger">
|
||||||
|
{{ 'requiredField' | translate }}
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label for="custId" class="text-nowrap">
|
||||||
|
{{ 'custId' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
class="password-wrapper position-relative w-100">
|
||||||
|
|
||||||
|
<input id="custId" type="text" class="form-control"
|
||||||
|
placeholder="{{ 'enterIdentityValue' | translate }}"
|
||||||
|
maxlength="500"
|
||||||
|
appNoWhitespaces rows="3" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6 ms-auto text-end">
|
||||||
|
<button
|
||||||
|
class="btn btn-primary waves-effect waves-light">{{'fetchCustomer'
|
||||||
|
| translate}}</button>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="col-xl-12 mt-4">
|
||||||
|
<div class="card border">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-section">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="card-body mt-2 p-0">
|
||||||
|
<div class="card mb-0 mt-2">
|
||||||
|
<div
|
||||||
|
class="card-header font-edit-13-child d-flex justify-content-between align-items-center">
|
||||||
|
{{'unblockUserDetails' | translate}}
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<div class="search-box">
|
||||||
|
<input type="text" class="form-control form-control-sm"
|
||||||
|
placeholder="{{ 'search' | translate }}">
|
||||||
|
<i class="fas fa-search search-icon"></i>
|
||||||
|
</div>
|
||||||
|
<i class="materialdesignicons">
|
||||||
|
<ng-container *ngIf="renewalDataExpanded; else collapsedIcon">
|
||||||
|
<i class="dripicons-chevron-up float-end"></i>
|
||||||
|
</ng-container>
|
||||||
|
<ng-template #collapsedIcon>
|
||||||
|
<i class="dripicons-chevron-down float-end"></i>
|
||||||
|
</ng-template>
|
||||||
|
</i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table mb-0 border">
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th>{{'firstName' | translate}}</th>
|
||||||
|
<th>{{'lastName' | translate}}</th>
|
||||||
|
<th>{{'cmpCuststatus' | translate}}</th>
|
||||||
|
<th>{{'cmpCustlastlogin' | translate}}</th>
|
||||||
|
<th>{{'accountNonLocked' | translate}}</th>
|
||||||
|
<th>{{'lockTime' | translate}}</th>
|
||||||
|
<th>{{'accountno' | translate}}</th>
|
||||||
|
<th>{{'phoneno' | translate}}</th>
|
||||||
|
<th>{{'action' | translate}}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<div
|
||||||
|
class="d-flex justify-content-center gap-2">
|
||||||
|
|
||||||
|
<button class="btn btn-info btn-sm"
|
||||||
|
title="View">
|
||||||
|
<i class="mdi mdi-eye-outline"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button class="btn btn-secondary btn-sm"
|
||||||
|
title="Edit">
|
||||||
|
<i class="fas fa-pen"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
|
||||||
|
<button class="btn btn-danger btn-sm"
|
||||||
|
title="Delete">
|
||||||
|
<i class="fas fa-trash-alt"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div
|
||||||
|
class="d-flex justify-content-between align-items-center mt-3">
|
||||||
|
<div class="form-group mb-0">
|
||||||
|
<ng-select class="form-select-sm"
|
||||||
|
[items]="pageSizeOptions" bindLabel="label"
|
||||||
|
bindValue="value" [(ngModel)]="itemsPerPage"
|
||||||
|
[searchable]="false" [clearable]="false"
|
||||||
|
[dropdownPosition]="'top'">
|
||||||
|
</ng-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-muted">
|
||||||
|
{{ 'page' | translate }} {{ 'of' | translate }} ({{
|
||||||
|
'totalItems' | translate }})
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="btn-group">
|
||||||
|
<button
|
||||||
|
class="btn btn-primary waves-effect waves-light">
|
||||||
|
{{ 'previous' | translate }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-primary waves-effect waves-light">
|
||||||
|
{{ 'next' | translate }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { IbUnblockUserComponent } from './ib-unblock-user.component';
|
||||||
|
|
||||||
|
describe('IbUnblockUserComponent', () => {
|
||||||
|
let component: IbUnblockUserComponent;
|
||||||
|
let fixture: ComponentFixture<IbUnblockUserComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [IbUnblockUserComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(IbUnblockUserComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { NgSelectModule } from '@ng-select/ng-select';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { pageSizeOptions } from '../../utils/app.constants';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-ib-unblock-user',
|
||||||
|
imports: [TranslateModule, FormsModule, NgSelectModule, CommonModule, ReactiveFormsModule],
|
||||||
|
templateUrl: './ib-unblock-user.component.html',
|
||||||
|
styleUrl: './ib-unblock-user.component.scss'
|
||||||
|
})
|
||||||
|
export class IbUnblockUserComponent {
|
||||||
|
renewalDataExpanded: boolean = true
|
||||||
|
itemsPerPage: number = 5;
|
||||||
|
pageSizeOptions = pageSizeOptions
|
||||||
|
optionValue: any;
|
||||||
|
|
||||||
|
itemsPerPageChanged() {}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,199 @@
|
|||||||
|
<div id="layout-wrapper">
|
||||||
|
<div class="inner-pg-sp">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="d-sm-flex align-items-center justify-content-between navbar-header p-0">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="col-xl-12 mt-4">
|
||||||
|
<div class="card border">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-section">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="card-body mt-2 p-0">
|
||||||
|
<div class="card mb-0 mt-2">
|
||||||
|
<div
|
||||||
|
class="card-header font-edit-13-child d-flex justify-content-between align-items-center">
|
||||||
|
{{'purposeSetup' | translate}}
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form>
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label for="purpcodeLabel" class="text-nowrap">
|
||||||
|
{{ 'purpcodeLabel' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="password-wrapper position-relative w-100">
|
||||||
|
<div class="d-flex flex-row align-items-stretch">
|
||||||
|
<input type="text" id="purpcodeLabel"
|
||||||
|
class="form-control"
|
||||||
|
|
||||||
|
placeholder="{{ 'purpcodePlaceholder' | translate }}" appNoWhitespaces
|
||||||
|
/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- <div class="text-danger">
|
||||||
|
{{ 'requiredField' | translate }}
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-start gap-2">
|
||||||
|
<label for="purpdescLabel"
|
||||||
|
class="text-nowrap mt-2">
|
||||||
|
{{ 'purpdescLabel' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="password-wrapper position-relative w-100">
|
||||||
|
|
||||||
|
<input id="purpdescLabel"
|
||||||
|
class="form-control"
|
||||||
|
|
||||||
|
maxlength="500"
|
||||||
|
placeholder="{{ 'purpdescPlaceholder' | translate }}" appNoWhitespaces
|
||||||
|
rows="3" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6 ms-auto text-end">
|
||||||
|
<button
|
||||||
|
class="btn btn-primary waves-effect waves-light"
|
||||||
|
|
||||||
|
>{{'save' | translate}}</button>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="col-xl-12 mt-4">
|
||||||
|
<div class="card border">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-section">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="card-body mt-2 p-0">
|
||||||
|
<div class="card mb-0 mt-2">
|
||||||
|
<div class="card-header font-edit-13-child d-flex justify-content-between align-items-center">
|
||||||
|
{{'transactionDetails' | translate}}
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<div class="search-box">
|
||||||
|
<input type="text" class="form-control form-control-sm"
|
||||||
|
placeholder="{{ 'search' | translate }}">
|
||||||
|
<i class="fas fa-search search-icon"></i>
|
||||||
|
</div>
|
||||||
|
<i class="materialdesignicons">
|
||||||
|
<ng-container *ngIf="renewalDataExpanded; else collapsedIcon">
|
||||||
|
<i class="dripicons-chevron-up float-end"></i>
|
||||||
|
</ng-container>
|
||||||
|
<ng-template #collapsedIcon>
|
||||||
|
<i class="dripicons-chevron-down float-end"></i>
|
||||||
|
</ng-template>
|
||||||
|
</i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table mb-0 border">
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th>{{'smsOrgaCode' | translate}}</th>
|
||||||
|
<th>{{'purpcodeLabel' | translate}}</th>
|
||||||
|
<th>{{'purpdescLabel' | translate}}</th>
|
||||||
|
<th>{{'action' | translate}}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<div class="d-flex justify-content-center gap-2">
|
||||||
|
|
||||||
|
<button class="btn btn-info btn-sm" title="View">
|
||||||
|
<i class="mdi mdi-eye-outline"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button class="btn btn-secondary btn-sm" title="Edit">
|
||||||
|
<i class="fas fa-pen"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
|
||||||
|
<button class="btn btn-danger btn-sm" title="Delete">
|
||||||
|
<i class="fas fa-trash-alt"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="d-flex justify-content-between align-items-center mt-3">
|
||||||
|
<div class="form-group mb-0">
|
||||||
|
<ng-select class="form-select-sm"
|
||||||
|
[items]="pageSizeOptions"
|
||||||
|
bindLabel="label"
|
||||||
|
bindValue="value"
|
||||||
|
[(ngModel)]="itemsPerPage"
|
||||||
|
[searchable]="false"
|
||||||
|
[clearable]="false"
|
||||||
|
[dropdownPosition]="'top'">
|
||||||
|
</ng-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-muted">
|
||||||
|
{{ 'page' | translate }} {{ 'of' | translate }} ({{ 'totalItems' | translate }})
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="btn-group">
|
||||||
|
<button class="btn btn-primary waves-effect waves-light">
|
||||||
|
{{ 'previous' | translate }}
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-primary waves-effect waves-light">
|
||||||
|
{{ 'next' | translate }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { TranPurposeSetupComponent } from './tran-purpose-setup.component';
|
||||||
|
|
||||||
|
describe('TranPurposeSetupComponent', () => {
|
||||||
|
let component: TranPurposeSetupComponent;
|
||||||
|
let fixture: ComponentFixture<TranPurposeSetupComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [TranPurposeSetupComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(TranPurposeSetupComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { NgSelectModule } from '@ng-select/ng-select';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { pageSizeOptions } from '../../utils/app.constants';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-tran-purpose-setup',
|
||||||
|
imports: [TranslateModule, CommonModule, ReactiveFormsModule, FormsModule, NgSelectModule],
|
||||||
|
templateUrl: './tran-purpose-setup.component.html',
|
||||||
|
styleUrl: './tran-purpose-setup.component.scss'
|
||||||
|
})
|
||||||
|
export class TranPurposeSetupComponent {
|
||||||
|
pageSizeOptions = pageSizeOptions
|
||||||
|
renewalDataExpanded: any;
|
||||||
|
itemsPerPage: number = 5;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,209 @@
|
|||||||
|
<div id="layout-wrapper">
|
||||||
|
<div class="inner-pg-sp">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="d-sm-flex align-items-center justify-content-between navbar-header p-0">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="col-xl-12 mt-4">
|
||||||
|
<div class="card border">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-section">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="card-body mt-2 p-0">
|
||||||
|
<div class="card mb-0 mt-2">
|
||||||
|
<div
|
||||||
|
class="card-header font-edit-13-child d-flex justify-content-between align-items-center">
|
||||||
|
{{'loggerManager' | translate}}
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form>
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label for="fromDate" class="text-nowrap">
|
||||||
|
{{ 'fromDate' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
class="password-wrapper position-relative w-100">
|
||||||
|
<div
|
||||||
|
class="d-flex flex-row align-items-stretch">
|
||||||
|
<input type="date" id="fromDate"
|
||||||
|
class="form-control"
|
||||||
|
appNoWhitespaces />
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- <div class="text-danger">
|
||||||
|
{{ 'requiredField' | translate }}
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-start gap-2">
|
||||||
|
<label for="toDate" class="text-nowrap mt-2">
|
||||||
|
{{ 'toDate' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
class="password-wrapper position-relative w-100">
|
||||||
|
|
||||||
|
<input id="toDate" type="date" class="form-control"
|
||||||
|
maxlength="500"
|
||||||
|
appNoWhitespaces rows="3" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6 ms-auto text-end">
|
||||||
|
<button
|
||||||
|
class="btn btn-primary waves-effect waves-light">{{'findLogs'
|
||||||
|
| translate}}</button>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="col-xl-12 mt-4">
|
||||||
|
<div class="card border">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-section">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="card-body mt-2 p-0">
|
||||||
|
<div class="card mb-0 mt-2">
|
||||||
|
<div
|
||||||
|
class="card-header font-edit-13-child d-flex justify-content-between align-items-center">
|
||||||
|
{{'loggerManagerDetails' | translate}}
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<div class="search-box">
|
||||||
|
<input type="text" class="form-control form-control-sm"
|
||||||
|
placeholder="{{ 'search' | translate }}">
|
||||||
|
<i class="fas fa-search search-icon"></i>
|
||||||
|
</div>
|
||||||
|
<i class="materialdesignicons">
|
||||||
|
<ng-container *ngIf="renewalDataExpanded; else collapsedIcon">
|
||||||
|
<i class="dripicons-chevron-up float-end"></i>
|
||||||
|
</ng-container>
|
||||||
|
<ng-template #collapsedIcon>
|
||||||
|
<i class="dripicons-chevron-down float-end"></i>
|
||||||
|
</ng-template>
|
||||||
|
</i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table mb-0 border">
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th>{{'loggingID' | translate}}</th>
|
||||||
|
<th>{{'loggingRequestUri' | translate}}</th>
|
||||||
|
<th>{{'loggingResponseCode' | translate}}</th>
|
||||||
|
<th>{{'loggingRemoteIP' | translate}}</th>
|
||||||
|
<th>{{'loggingTimeTaken' | translate}}</th>
|
||||||
|
<th>{{'loggingDateTime' | translate}}</th>
|
||||||
|
<th>{{'loggingMethod' | translate}}</th>
|
||||||
|
<th>{{'action' | translate}}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<div
|
||||||
|
class="d-flex justify-content-center gap-2">
|
||||||
|
|
||||||
|
<button class="btn btn-info btn-sm"
|
||||||
|
title="View">
|
||||||
|
<i class="mdi mdi-eye-outline"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button class="btn btn-secondary btn-sm"
|
||||||
|
title="Edit">
|
||||||
|
<i class="fas fa-pen"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
|
||||||
|
<button class="btn btn-danger btn-sm"
|
||||||
|
title="Delete">
|
||||||
|
<i class="fas fa-trash-alt"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div
|
||||||
|
class="d-flex justify-content-between align-items-center mt-3">
|
||||||
|
<div class="form-group mb-0">
|
||||||
|
<ng-select class="form-select-sm"
|
||||||
|
[items]="pageSizeOptions" bindLabel="label"
|
||||||
|
bindValue="value" [(ngModel)]="itemsPerPage"
|
||||||
|
[searchable]="false" [clearable]="false"
|
||||||
|
[dropdownPosition]="'top'">
|
||||||
|
</ng-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-muted">
|
||||||
|
{{ 'page' | translate }} {{ 'of' | translate }} ({{
|
||||||
|
'totalItems' | translate }})
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="btn-group">
|
||||||
|
<button
|
||||||
|
class="btn btn-primary waves-effect waves-light">
|
||||||
|
{{ 'previous' | translate }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-primary waves-effect waves-light">
|
||||||
|
{{ 'next' | translate }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { LoggingComponent } from './logging.component';
|
||||||
|
|
||||||
|
describe('LoggingComponent', () => {
|
||||||
|
let component: LoggingComponent;
|
||||||
|
let fixture: ComponentFixture<LoggingComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [LoggingComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(LoggingComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { NgSelectModule } from '@ng-select/ng-select';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { pageSizeOptions } from '../utils/app.constants';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-logging',
|
||||||
|
imports: [TranslateModule, FormsModule, NgSelectModule, CommonModule, ReactiveFormsModule],
|
||||||
|
templateUrl: './logging.component.html',
|
||||||
|
styleUrl: './logging.component.scss'
|
||||||
|
})
|
||||||
|
export class LoggingComponent {
|
||||||
|
currentPage: number = 1;
|
||||||
|
pageSizeOptions = pageSizeOptions
|
||||||
|
renewalDataExpanded: boolean = true
|
||||||
|
itemsPerPage: number = 5;
|
||||||
|
searchText: any;
|
||||||
|
toggleCard(arg0: string) {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
nextPage() {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
logsForm: any;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
export interface ServerException {
|
||||||
|
error: HttpError;
|
||||||
|
}
|
||||||
|
export interface HttpError {
|
||||||
|
errorCode: string;
|
||||||
|
arguments: Array<any>;
|
||||||
|
}
|
||||||
|
export interface FunctionReturn {
|
||||||
|
returnCode: number;
|
||||||
|
messageCode: string;
|
||||||
|
}
|
||||||
|
export interface FunctionReturnDetail extends FunctionReturn {
|
||||||
|
arguments: Array<any>;
|
||||||
|
}
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
export class User {
|
||||||
|
Username: string="";
|
||||||
|
Email?: string="";
|
||||||
|
Password: string="";
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
export interface ServerException {
|
||||||
|
error: HttpError;
|
||||||
|
}
|
||||||
|
export interface HttpError {
|
||||||
|
errorCode: string;
|
||||||
|
arguments: Array<any>;
|
||||||
|
}
|
||||||
|
export interface FunctionReturn {
|
||||||
|
returnCode: number;
|
||||||
|
messageCode: string;
|
||||||
|
}
|
||||||
|
export interface FunctionReturnDetail extends FunctionReturn {
|
||||||
|
arguments: Array<any>;
|
||||||
|
}
|
||||||
@ -0,0 +1,89 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { tap } from 'rxjs/operators';
|
||||||
|
import { HttpService } from '../shared/services/http.service';
|
||||||
|
import { MiscService } from '../shared/services/misc.service';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { User } from '../models/user';
|
||||||
|
import { HttpErrorResponse } from '@angular/common/http';
|
||||||
|
import { CONSTANTS } from '../utils/app.constants';
|
||||||
|
import { StorageService } from '../shared/services/storage.service';
|
||||||
|
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class AuthService {
|
||||||
|
|
||||||
|
constructor(private httpService: HttpService, private miscService: MiscService, private router: Router, private storageService: StorageService) { }
|
||||||
|
firstLogin: boolean = false;
|
||||||
|
private token: string = "";
|
||||||
|
|
||||||
|
async login(User_Data: User) {
|
||||||
|
let login = false;
|
||||||
|
let userId = User_Data.Username;
|
||||||
|
let password = User_Data.Password;
|
||||||
|
let data = { "userId": User_Data.Username, "userPassword": btoa(User_Data.Password) };
|
||||||
|
|
||||||
|
let url = '/loginUser';
|
||||||
|
|
||||||
|
let response: any = await this.httpService.postRequest(url, data)!.toPromise();
|
||||||
|
if (!(response instanceof HttpErrorResponse)) {
|
||||||
|
if ((await response["errorMessage"] == undefined)) {
|
||||||
|
if (response) {
|
||||||
|
login = true;
|
||||||
|
localStorage.setItem('USERKEY', userId);
|
||||||
|
let res = JSON.parse(JSON.stringify(response));
|
||||||
|
let permission = JSON.parse(res['userPermission']);
|
||||||
|
localStorage.setItem('SIDENAV', res['userPermission']);
|
||||||
|
this.firstLogin = res['firstLogin'];
|
||||||
|
localStorage.setItem('USERNAME', res['userName']);
|
||||||
|
localStorage.setItem('token', res['token'])
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let res = response;
|
||||||
|
return res;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IsLoggedIn() {
|
||||||
|
if (this.storageService.getItem('USERKEY') !== null)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
logout() {
|
||||||
|
window.history.state;
|
||||||
|
localStorage.clear();
|
||||||
|
this.router.navigate(['login'])
|
||||||
|
}
|
||||||
|
|
||||||
|
getToken(): string {
|
||||||
|
this.token = localStorage.getItem('token') || "";
|
||||||
|
return this.token;
|
||||||
|
}
|
||||||
|
|
||||||
|
setToken(token: string) {
|
||||||
|
this.token = token;
|
||||||
|
localStorage.setItem('token', token);
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshToken() {
|
||||||
|
let uCreds = { token: this.getToken() };
|
||||||
|
let porOrgacode = CONSTANTS.POR_ORGACODE;
|
||||||
|
let refreshTokenData: any = {
|
||||||
|
cmpUserId: localStorage.getItem('USERKEY'),
|
||||||
|
token: uCreds.token,
|
||||||
|
porOrgacode: porOrgacode
|
||||||
|
}
|
||||||
|
return this.httpService.postRequest("/refreshToken", refreshTokenData)!.pipe(
|
||||||
|
tap((response: any) => {
|
||||||
|
localStorage.removeItem('token')
|
||||||
|
localStorage.setItem('token', JSON.stringify(response.token));
|
||||||
|
this.setToken(response.token);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { ToastrService } from 'ngx-toastr';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class MessageService {
|
||||||
|
|
||||||
|
constructor(private toastr: ToastrService) { }
|
||||||
|
|
||||||
|
Success(Message: string,) {
|
||||||
|
this.toastr.success(Message, "Success", { tapToDismiss: true, progressBar: true, progressAnimation: 'increasing' });
|
||||||
|
}
|
||||||
|
Show(Message: string, Title: string) {
|
||||||
|
this.toastr.success(Message, Title, { tapToDismiss: true, progressBar: true, progressAnimation: 'increasing' });
|
||||||
|
}
|
||||||
|
Error(Message: string) {
|
||||||
|
this.toastr.error(Message, "Error", { tapToDismiss: true, progressBar: true, progressAnimation: 'increasing' });
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { BehaviorSubject } from 'rxjs';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class SidebarService {
|
||||||
|
private isSidebarOpen = new BehaviorSubject<boolean>(false);
|
||||||
|
public sidebarState$ = this.isSidebarOpen.asObservable();
|
||||||
|
currentSubModule:string;
|
||||||
|
constructor() {
|
||||||
|
this.currentSubModule = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleSidebar(): void {
|
||||||
|
this.isSidebarOpen.next(!this.isSidebarOpen.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { NgxSpinnerService } from 'ngx-spinner';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class SpinnerService {
|
||||||
|
|
||||||
|
constructor(private spinner: NgxSpinnerService) { }
|
||||||
|
|
||||||
|
IsBusy(state:boolean) {
|
||||||
|
if (state == true)
|
||||||
|
this.spinner.show();
|
||||||
|
else
|
||||||
|
this.spinner.hide();
|
||||||
|
}}
|
||||||
@ -0,0 +1,76 @@
|
|||||||
|
<div class="col-md-10 mx-auto" id="page-topbar">
|
||||||
|
<div class="p-0">
|
||||||
|
<div class="navbar-header shadow-lg d-flex justify-content-between align-items-center w-100">
|
||||||
|
|
||||||
|
<!-- Left Section -->
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
|
||||||
|
<!-- Logo Section -->
|
||||||
|
<div class="navbar-brand-box bg-primary me-2">
|
||||||
|
<a routerLink="/home/dashboard" class="logo logo-dark">
|
||||||
|
<span class="logo-sm">
|
||||||
|
<img src="assets/images/mfsys-logo.png" alt="Logo" height="30" />
|
||||||
|
</span>
|
||||||
|
<span class="logo-lg">
|
||||||
|
<img src="assets/images/mfsys-logoo.png" alt="Logo" height="60" />
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
<a routerLink="/home/dashboard" class="logo logo-light">
|
||||||
|
<span class="logo-sm">
|
||||||
|
<img src="assets/images/mfsys-logo.png" alt="Logo" height="30" />
|
||||||
|
</span>
|
||||||
|
<span class="logo-lg">
|
||||||
|
<img src="assets/images/mfsys-logoo.png" alt="Logo" height="60" />
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Vertical Menu Button -->
|
||||||
|
<button type="button"
|
||||||
|
class="btn btn-sm px-3 text-muted header-item waves-effect"
|
||||||
|
id="vertical-menu-btn">
|
||||||
|
<img src="assets/images/data-transfers.png" alt="Logo" style="width: 16px; margin: -4px;" />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- Submodule Text -->
|
||||||
|
<div class="d-none d-lg-block ms-3">
|
||||||
|
<p class="text-muted mt-3 fw-normal mb-0">
|
||||||
|
{{ (sidebarService.currentSubModule | translate) }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Right Section -->
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
|
||||||
|
<div class="d-none d-lg-inline-block me-3">
|
||||||
|
<label class="text-muted fw-normal mb-0"
|
||||||
|
[title]="mismatchedDates"
|
||||||
|
[style]="{'color': dateColor}"
|
||||||
|
style="font-size: 14px;">
|
||||||
|
{{'date' | translate}}: {{date}}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="dropdown d-inline-block profile-dropdown">
|
||||||
|
<button type="button"
|
||||||
|
class="btn header-item waves-effect p-0 d-flex align-items-center"
|
||||||
|
id="page-header-user-dropdown"
|
||||||
|
(click)="toggleDropdown()"
|
||||||
|
aria-haspopup="true"
|
||||||
|
[attr.aria-expanded]="isDropdownVisible ? 'true' : 'false'">
|
||||||
|
<img class="rounded-circle header-profile-user" src="assets/images/user-icon.png" alt="user-icon" />
|
||||||
|
<span class="d-none d-xl-inline-block ms-2 text-muted">{{username}}</span>
|
||||||
|
<i class="mdi mdi-chevron-down text-muted d-xl-inline-block font-size-22"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="dropdown-menu dropdown-menu-end" [ngClass]="{'show': isDropdownVisible}">
|
||||||
|
<a class="dropdown-item text-danger" (click)="logout()">
|
||||||
|
<i class="bx bx-power-off font-size-16 align-middle me-1 text-danger"></i> {{ 'logout' | translate }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { HeaderComponent } from './header.component';
|
||||||
|
|
||||||
|
describe('HeaderComponent', () => {
|
||||||
|
let component: HeaderComponent;
|
||||||
|
let fixture: ComponentFixture<HeaderComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [HeaderComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(HeaderComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,181 @@
|
|||||||
|
import { Component, HostListener, Inject, PLATFORM_ID } from '@angular/core';
|
||||||
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
|
import { SidebarService } from '../../../services/sidebar.service';
|
||||||
|
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
||||||
|
import { StorageService } from '../../services/storage.service';
|
||||||
|
import { AuthService } from '../../../services/auth.service';
|
||||||
|
import { isPlatformBrowser, formatDate, CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-header',
|
||||||
|
imports: [TranslateModule, CommonModule],
|
||||||
|
templateUrl: './header.component.html',
|
||||||
|
styleUrl: './header.component.scss'
|
||||||
|
})
|
||||||
|
export class HeaderComponent {
|
||||||
|
isDropdownVisible: boolean;
|
||||||
|
isVacDropdownVisible: boolean;
|
||||||
|
isNotificationsVisible: boolean;
|
||||||
|
notifications = [
|
||||||
|
{
|
||||||
|
imgSrc: '',
|
||||||
|
title: 'Salena Layfield',
|
||||||
|
message: 'As a skeptical Cambridge friend of mine occidental.',
|
||||||
|
timeAgo: '1 hour ago'
|
||||||
|
},
|
||||||
|
];
|
||||||
|
direction: string = 'ltr';
|
||||||
|
userString;
|
||||||
|
user;
|
||||||
|
username;
|
||||||
|
mismatchedDates: string = "";
|
||||||
|
dateColor = "black";
|
||||||
|
date: any;
|
||||||
|
vacName: any;
|
||||||
|
allVacs: any;
|
||||||
|
constructor(
|
||||||
|
private router: Router,
|
||||||
|
public sidebarService: SidebarService,
|
||||||
|
private translate: TranslateService,
|
||||||
|
@Inject(PLATFORM_ID) private platformId: Object,
|
||||||
|
private storageService: StorageService,
|
||||||
|
public authService: AuthService
|
||||||
|
) {
|
||||||
|
this.isDropdownVisible = false;
|
||||||
|
this.isVacDropdownVisible = false;
|
||||||
|
this.isNotificationsVisible = false;
|
||||||
|
this.userString = this.storageService.getItem('user');
|
||||||
|
this.user = JSON.parse(this.userString as string);
|
||||||
|
this.username = this.user?.username;
|
||||||
|
this.date = new Date().toISOString().split('T')[0];
|
||||||
|
}
|
||||||
|
ngOnInit(): void {
|
||||||
|
if (typeof document !== 'undefined' && typeof window !== 'undefined') {
|
||||||
|
this.initializeVerticalMenuToggle();
|
||||||
|
this.initializeFullscreenToggle();
|
||||||
|
const body = document.body;
|
||||||
|
if (window.innerWidth >= 992) {
|
||||||
|
const isCollapsed = body.classList.toggle('sidebar-enable');
|
||||||
|
this.storageService.setItem('sidebarState', isCollapsed ? 'expanded' : 'collapsed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit(): void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
initializeVerticalMenuToggle(): void {
|
||||||
|
if (isPlatformBrowser(this.platformId)) {
|
||||||
|
const verticalMenuBtn = document.getElementById('vertical-menu-btn');
|
||||||
|
if (window.innerWidth <= 992) {
|
||||||
|
const body = document.body;
|
||||||
|
body.classList.add('vertical-collpsed');
|
||||||
|
}
|
||||||
|
if (verticalMenuBtn) {
|
||||||
|
verticalMenuBtn.addEventListener('click', this.toggleSidebar.bind(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
initializeFullscreenToggle(): void {
|
||||||
|
if (isPlatformBrowser(this.platformId)) {
|
||||||
|
const fullscreenButton = document.querySelector<HTMLButtonElement>('[data-bs-toggle="fullscreen"]');
|
||||||
|
if (fullscreenButton) {
|
||||||
|
fullscreenButton.addEventListener("click", () => {
|
||||||
|
if (!document.fullscreenElement) {
|
||||||
|
this.toggleFullscreen(true);
|
||||||
|
} else {
|
||||||
|
this.toggleFullscreen(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleFullscreen(enter: boolean): void {
|
||||||
|
if (isPlatformBrowser(this.platformId)) {
|
||||||
|
if (enter) {
|
||||||
|
document.documentElement.requestFullscreen();
|
||||||
|
} else {
|
||||||
|
document.exitFullscreen();
|
||||||
|
}
|
||||||
|
document.body.classList.toggle('fullscreen-enable', enter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleSidebar(): void {
|
||||||
|
if (isPlatformBrowser(this.platformId)) {
|
||||||
|
const body = document.body;
|
||||||
|
const isSidebarEnabled = body.classList.toggle('sidebar-enable');
|
||||||
|
if (window.innerWidth >= 992) {
|
||||||
|
const isCollapsed = body.classList.toggle('vertical-collpsed');
|
||||||
|
this.storageService.setItem('sidebarState', isCollapsed ? 'collapsed' : 'expanded');
|
||||||
|
if (isCollapsed) {
|
||||||
|
const subMenus = document.querySelectorAll('.sub-menu');
|
||||||
|
subMenus.forEach(menu => {
|
||||||
|
(menu as HTMLElement).style.display = '';
|
||||||
|
menu.setAttribute('aria-expanded', 'false');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const subMenus = document.querySelectorAll('.sub-menu');
|
||||||
|
subMenus.forEach(menu => {
|
||||||
|
(menu as HTMLElement).style.display = 'none';
|
||||||
|
menu.setAttribute('aria-expanded', 'false');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
body.classList.remove('vertical-collpsed');
|
||||||
|
this.storageService.setItem('sidebarState', 'expanded');
|
||||||
|
const subMenus = document.querySelectorAll('.sub-menu');
|
||||||
|
subMenus.forEach(menu => {
|
||||||
|
(menu as HTMLElement).style.display = 'none';
|
||||||
|
menu.setAttribute('aria-expanded', 'false');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleDropdown(): void {
|
||||||
|
this.isDropdownVisible = !this.isDropdownVisible;
|
||||||
|
this.isNotificationsVisible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleVacDropdown(): void {
|
||||||
|
this.isVacDropdownVisible = !this.isVacDropdownVisible;
|
||||||
|
this.isNotificationsVisible = false;
|
||||||
|
}
|
||||||
|
toggleNotifications(): void {
|
||||||
|
this.isNotificationsVisible = !this.isNotificationsVisible;
|
||||||
|
this.isDropdownVisible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// toggleSidebar() {
|
||||||
|
// this.sidebarService.toggleSidebar();
|
||||||
|
// }
|
||||||
|
logout() {
|
||||||
|
this.authService.logout();
|
||||||
|
}
|
||||||
|
@HostListener('document:click', ['$event'])
|
||||||
|
handleClickOutside(event: MouseEvent) {
|
||||||
|
const targetElement = event.target as HTMLElement;
|
||||||
|
const isClickInsideProfileDropdown = targetElement.closest('.profile-dropdown');
|
||||||
|
const isClickInsideVacDropdown = targetElement.closest('.vac-dropdown');
|
||||||
|
if (!isClickInsideProfileDropdown) {
|
||||||
|
this.isDropdownVisible = false;
|
||||||
|
}
|
||||||
|
if (!isClickInsideVacDropdown) {
|
||||||
|
this.isVacDropdownVisible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
formatDate(date?: Date) {
|
||||||
|
if ((date && !isNaN(date.getTime())) || (date != null || date != undefined)) {
|
||||||
|
// Adil 5152 - Changing the Date Locale based on the language selected
|
||||||
|
return formatDate(date, 'EEEE, d MMMM yyyy', 'en');
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
@if (loading$ | async) {
|
||||||
|
<div class="loader-overlay">
|
||||||
|
<div class="loader"></div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
.loader-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loader {
|
||||||
|
border: 16px solid #f3f3f3;
|
||||||
|
border-radius: 50%;
|
||||||
|
border-top: 16px solid #3498db;
|
||||||
|
width: 120px;
|
||||||
|
height: 120px;
|
||||||
|
animation: spin 2s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
0% { transform: rotate(0deg); }
|
||||||
|
100% { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { LoaderComponent } from './loader.component';
|
||||||
|
|
||||||
|
describe('LoaderComponent', () => {
|
||||||
|
let component: LoaderComponent;
|
||||||
|
let fixture: ComponentFixture<LoaderComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [LoaderComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(LoaderComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { LoadingService } from '../../services/loading.service';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-loader',
|
||||||
|
imports: [CommonModule],
|
||||||
|
templateUrl: './loader.component.html',
|
||||||
|
styleUrl: './loader.component.scss'
|
||||||
|
})
|
||||||
|
export class LoaderComponent {
|
||||||
|
loading$: Observable<boolean>;
|
||||||
|
|
||||||
|
constructor(private loadingService: LoadingService) {
|
||||||
|
this.loading$ = this.loadingService.loading$;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
<button class="btn btn-light lh-sm" type="button" (click)="togglePassword()"><i [hidden]="!this.showPassword" class="mdi mdi-eye-off-outline"></i><i class="mdi mdi-eye-outline" [hidden]="this.showPassword"></i></button>
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { PasswordHideShowComponent } from './password-hide-show.component';
|
||||||
|
|
||||||
|
describe('PasswordHideShowComponent', () => {
|
||||||
|
let component: PasswordHideShowComponent;
|
||||||
|
let fixture: ComponentFixture<PasswordHideShowComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [PasswordHideShowComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(PasswordHideShowComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-password-hide-show',
|
||||||
|
imports: [],
|
||||||
|
templateUrl: './password-hide-show.component.html',
|
||||||
|
styleUrl: './password-hide-show.component.scss'
|
||||||
|
})
|
||||||
|
export class PasswordHideShowComponent {
|
||||||
|
@Output() onEyeClick = new EventEmitter();
|
||||||
|
@Input() showPassword : boolean = false;
|
||||||
|
inputType : String = '';
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
togglePassword(){
|
||||||
|
this.showPassword = !this.showPassword;
|
||||||
|
this.onEyeClick.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,108 @@
|
|||||||
|
<div class="vertical-menu bg-primary" (click)="handleMenuClick($event)">
|
||||||
|
<div id="sidebar-menu" class="hidden-scroll">
|
||||||
|
<ul class="metismenu list-unstyled" id="side-menu">
|
||||||
|
<li>
|
||||||
|
<a href="javascript: void(0);" routerLink="/home/dashboard" routerLinkActive="mm-active">
|
||||||
|
<i class="fa fa-home"></i>
|
||||||
|
<span>{{ 'dashboard' | translate }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:void(0);" class="has-arrow waves-effect" (click)="toggleMenu($event)">
|
||||||
|
<i class="fa fa-user-secret"></i>
|
||||||
|
<span>{{ 'UserManagement' | translate }}</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<ul class="sub-menu" aria-expanded="false">
|
||||||
|
<li>
|
||||||
|
<a routerLink="/home/thirdPartyRegistration" routerLinkActive="mm-active">
|
||||||
|
<span> {{ 'thirdPartyRegistration' | translate }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a routerLink="/home/setupUser" routerLinkActive="mm-active">
|
||||||
|
<span>{{ 'setupUser' | translate }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a routerLink="/home/resetPassword" routerLinkActive="mm-active">
|
||||||
|
<span> {{ 'resetPassword' | translate }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a routerLink="/home/changePassword" routerLinkActive="mm-active">
|
||||||
|
<span> {{ 'changePassword' | translate }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:void(0);" class="has-arrow waves-effect" (click)="toggleMenu($event)">
|
||||||
|
<i class="fa fa-history"></i>
|
||||||
|
<span>{{ 'Logging' | translate }}</span>
|
||||||
|
</a>
|
||||||
|
<ul class="sub-menu" aria-expanded="false">
|
||||||
|
<li>
|
||||||
|
<a routerLink="/home/loggerManager" routerLinkActive="mm-active">
|
||||||
|
<span> {{ 'loggerManager' | translate }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:void(0);" class="has-arrow waves-effect" (click)="toggleMenu($event)">
|
||||||
|
<i class="mdi mdi-comment-outline"></i>
|
||||||
|
<span>{{ 'SMSBanking' | translate }}</span>
|
||||||
|
</a>
|
||||||
|
<ul class="sub-menu" aria-expanded="false">
|
||||||
|
<li>
|
||||||
|
<a routerLink="/home/smsLogger" routerLinkActive="mm-active">
|
||||||
|
<span> {{ 'smsLogger' | translate }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a routerLink="/home/smsGateway" routerLinkActive="mm-active">
|
||||||
|
<span> {{ 'smsGateway' | translate }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:void(0);" class="has-arrow waves-effect" (click)="toggleMenu($event)">
|
||||||
|
<i class="mdi mdi-comment-outline"></i>
|
||||||
|
<span>{{ 'ibSupport' | translate }}</span>
|
||||||
|
</a>
|
||||||
|
<ul class="sub-menu" aria-expanded="false">
|
||||||
|
<li>
|
||||||
|
<a routerLink="/home/ibUnblockUser" routerLinkActive="mm-active">
|
||||||
|
<span> {{ 'ibUnblockUser' | translate }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a routerLink="/home/feedbackSetup" routerLinkActive="mm-active">
|
||||||
|
<span> {{ 'feedbackSetup' | translate }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a routerLink="/home/purposeSetup" routerLinkActive="mm-active">
|
||||||
|
<span> {{ 'purposeSetup' | translate }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="javascript:void(0);" class="has-arrow waves-effect" (click)="toggleMenu($event)">
|
||||||
|
<i class='fa fa-lock'></i>
|
||||||
|
<span>{{ 'Permissions' | translate }}</span>
|
||||||
|
</a>
|
||||||
|
<ul class="sub-menu" aria-expanded="false">
|
||||||
|
<li>
|
||||||
|
<a routerLink="/home/permissions" routerLinkActive="mm-active">
|
||||||
|
<span> {{ 'permissions' | translate }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
.active-submenu {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.hidden-scroll {
|
||||||
|
overflow-y: auto;
|
||||||
|
-ms-overflow-style: none;
|
||||||
|
scrollbar-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden-scroll::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#sidebar-menu {
|
||||||
|
height: calc(100vh - 60px);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
#sidebar-menu {
|
||||||
|
height: calc(100vh - 100px);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.sub-menu {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-menu[aria-expanded="true"] {
|
||||||
|
display:block;
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { SideNavComponent } from './side-nav.component';
|
||||||
|
|
||||||
|
describe('SideNavComponent', () => {
|
||||||
|
let component: SideNavComponent;
|
||||||
|
let fixture: ComponentFixture<SideNavComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [SideNavComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(SideNavComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,101 @@
|
|||||||
|
import { Component, Inject, PLATFORM_ID } from '@angular/core';
|
||||||
|
import { FormGroup } from '@angular/forms';
|
||||||
|
import { SidebarService } from '../../../services/sidebar.service';
|
||||||
|
import { StorageService } from '../../services/storage.service';
|
||||||
|
import { isPlatformBrowser } from '@angular/common';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-side-nav',
|
||||||
|
imports: [TranslateModule, RouterModule],
|
||||||
|
templateUrl: './side-nav.component.html',
|
||||||
|
styleUrl: './side-nav.component.scss',
|
||||||
|
})
|
||||||
|
export class SideNavComponent {
|
||||||
|
isDropdownVisible = false;
|
||||||
|
isNotificationsVisible = false;
|
||||||
|
searchForm!: FormGroup;
|
||||||
|
permissions: any = {};
|
||||||
|
activeMenu: string | null = null;
|
||||||
|
direction: string = 'ltr';
|
||||||
|
constructor(
|
||||||
|
private sidebarService: SidebarService,
|
||||||
|
@Inject(PLATFORM_ID) private platformId: Object,
|
||||||
|
private storageService: StorageService
|
||||||
|
) {
|
||||||
|
// this.credentialService.getPermission().forEach((permission: any) => {
|
||||||
|
// this.permissions[permission.name] = permission.checked;
|
||||||
|
// if(permission.children.length>0){
|
||||||
|
// permission.children.forEach((child: any)=>{
|
||||||
|
// this.permissions[child.name] = child.checked;
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.sidebarService.currentSubModule = this.storageService.getItem('currentSubModule') ?? 'dashboard';
|
||||||
|
this.closeSidebarMenu();
|
||||||
|
}
|
||||||
|
closeSidebarMenu(): void {
|
||||||
|
if (isPlatformBrowser(this.platformId)) {
|
||||||
|
const subMenus = document.querySelectorAll('#sidebar-menu .sub-menu');
|
||||||
|
subMenus.forEach(menu => {
|
||||||
|
(menu as HTMLElement).style.display = 'none';
|
||||||
|
menu.setAttribute('aria-expanded', 'false');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleMenu(event: Event): void {
|
||||||
|
const target = event.currentTarget as HTMLElement;
|
||||||
|
const submenu = target.nextElementSibling as HTMLElement;
|
||||||
|
|
||||||
|
if (submenu && submenu.classList.contains('sub-menu')) {
|
||||||
|
const isExpanded = submenu.getAttribute('aria-expanded') === 'true';
|
||||||
|
submenu.style.display = isExpanded ? 'none' : '';
|
||||||
|
submenu.setAttribute('aria-expanded', isExpanded ? 'false' : 'true');
|
||||||
|
this.storageService.setItem('menuState' + submenu.id, isExpanded ? 'false' : 'true'); // Saving state per submenu
|
||||||
|
|
||||||
|
if (window.innerWidth <= 992) {
|
||||||
|
const links = submenu.querySelectorAll('a');
|
||||||
|
links.forEach(link => {
|
||||||
|
link.addEventListener('click', () => {
|
||||||
|
const body = document.body;
|
||||||
|
body.classList.remove('sidebar-enable'); // Hide the sidebar
|
||||||
|
this.storageService.setItem('sidebarState', 'collapsed'); // Store collapsed state
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleDropdown(): void {
|
||||||
|
this.isDropdownVisible = !this.isDropdownVisible;
|
||||||
|
this.isNotificationsVisible = false;
|
||||||
|
}
|
||||||
|
toggleNotifications(): void {
|
||||||
|
this.isNotificationsVisible = !this.isNotificationsVisible;
|
||||||
|
this.isDropdownVisible = false;
|
||||||
|
}
|
||||||
|
handleMenuClick(event: Event) {
|
||||||
|
const target = event.target as HTMLElement;
|
||||||
|
const linkElement = target.closest('a[routerLink]');
|
||||||
|
if (linkElement) {
|
||||||
|
const routerLink = linkElement.getAttribute('routerLink');
|
||||||
|
if (routerLink) {
|
||||||
|
this.onModuleClick(routerLink);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onModuleClick(route: string) {
|
||||||
|
const routeParts = route.split('/').filter(part => part.length > 0);
|
||||||
|
const lastRoutePart = routeParts[routeParts.length - 1];
|
||||||
|
this.sidebarService.currentSubModule = lastRoutePart;
|
||||||
|
if (isPlatformBrowser(this.platformId)) {
|
||||||
|
this.storageService.setItem('currentSubModule', lastRoutePart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
import { Inject, Injectable, PLATFORM_ID } from '@angular/core';
|
||||||
|
import { CanActivate, Router } from '@angular/router';
|
||||||
|
import { isPlatformBrowser } from '@angular/common';
|
||||||
|
|
||||||
|
import { AuthService } from '../../services/auth.service';
|
||||||
|
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class GAuth implements CanActivate {
|
||||||
|
|
||||||
|
constructor(private authservice: AuthService, private router: Router, @Inject(PLATFORM_ID) private platformId: object) { }
|
||||||
|
|
||||||
|
canActivate() {
|
||||||
|
if (this.authservice.IsLoggedIn()){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(isPlatformBrowser(this.platformId))
|
||||||
|
this.router.navigate(['login']);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,113 @@
|
|||||||
|
import { Injectable, Injector } from '@angular/core';
|
||||||
|
import {HttpRequest,HttpHandler,HttpEvent,HttpInterceptor,HttpErrorResponse} from '@angular/common/http';
|
||||||
|
import { BehaviorSubject, Observable, throwError } from 'rxjs';
|
||||||
|
import { AuthService } from '../../services/auth.service';
|
||||||
|
import { catchError, filter, switchMap, take, timeout } from 'rxjs/operators';
|
||||||
|
import { MiscService } from '../services/misc.service';
|
||||||
|
import { ServerException } from '../../services/app.server.response';
|
||||||
|
import { ErrorMessages } from '../../utils/enums';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AuthInterceptor implements HttpInterceptor {
|
||||||
|
private isRefreshing = false;
|
||||||
|
token: any;
|
||||||
|
private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(null);
|
||||||
|
private logoutChannel = new BroadcastChannel('logout_channel');
|
||||||
|
|
||||||
|
constructor(private injector: Injector,private authService:AuthService) {}
|
||||||
|
|
||||||
|
intercept(request: HttpRequest<any>, handler: HttpHandler): Observable<HttpEvent<any>> {
|
||||||
|
this.logoutChannel.onmessage = async (event) => {
|
||||||
|
if (event.data === 'logout') {
|
||||||
|
localStorage.clear();
|
||||||
|
window.location.href = '/#/auth';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (this.authService.getToken()) {
|
||||||
|
request = this.addToken(request, this.authService.getToken());
|
||||||
|
}
|
||||||
|
return handler.handle(request).pipe(catchError(error => {
|
||||||
|
if (error instanceof HttpErrorResponse && error.status === 401) {
|
||||||
|
return this.handleAuthError(request, handler);
|
||||||
|
} else {
|
||||||
|
this.handleServerError(error);
|
||||||
|
return throwError(error);
|
||||||
|
}
|
||||||
|
}))as Observable<HttpEvent<any>>;
|
||||||
|
}
|
||||||
|
private handleAuthError(request: HttpRequest<any>, handler: HttpHandler) {
|
||||||
|
if (!this.isRefreshing) {
|
||||||
|
this.isRefreshing = true;
|
||||||
|
this.refreshTokenSubject.next(null);
|
||||||
|
let authService: AuthService = this.injector.get(AuthService);
|
||||||
|
return authService.refreshToken().pipe(
|
||||||
|
switchMap((response: any) => {
|
||||||
|
this.isRefreshing = false;
|
||||||
|
this.refreshTokenSubject.next(response.token);
|
||||||
|
return handler.handle(this.addToken(request, response.token)).pipe(catchError(error => {
|
||||||
|
this.handleServerError(error);
|
||||||
|
return throwError(error);
|
||||||
|
}));
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
return this.refreshTokenSubject.pipe(
|
||||||
|
filter(token => token != null),
|
||||||
|
take(1),
|
||||||
|
switchMap(token => {
|
||||||
|
return handler.handle(this.addToken(request, token));
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private handleServerError(error: HttpErrorResponse) {
|
||||||
|
let url: string = error.url as string;
|
||||||
|
let moduleName: string = "";
|
||||||
|
if (url != null && url != undefined) {
|
||||||
|
moduleName = url.split(':').length > 2 ?
|
||||||
|
url.split(':')[2].split('/')[1] :
|
||||||
|
url.split('/')[3];
|
||||||
|
}
|
||||||
|
let authService: AuthService = this.injector.get(AuthService);
|
||||||
|
let miscService: MiscService = this.injector.get(MiscService);
|
||||||
|
switch (error.status) {
|
||||||
|
case 400:
|
||||||
|
let errorResponse: ServerException = error as ServerException;
|
||||||
|
if (errorResponse.error && errorResponse.error.errorCode != null) {
|
||||||
|
errorResponse.error.arguments.forEach((argument, index) => {
|
||||||
|
if (miscService.getErrorMessageTranslation(argument) != argument) {
|
||||||
|
errorResponse.error.arguments[index] = miscService.getErrorMessageTranslation(argument);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
miscService.handleError(errorResponse.error.errorCode);
|
||||||
|
} else {
|
||||||
|
miscService.handleError(ErrorMessages.BAD_REQUEST, [moduleName.toUpperCase()]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 401:
|
||||||
|
miscService.handleError(ErrorMessages.UNAUTHORIZED_REQUEST,[error.error.message]);
|
||||||
|
authService.logout();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 403:
|
||||||
|
miscService.handleError(ErrorMessages.FORBIDDEN_REQUEST,[]);
|
||||||
|
authService.logout();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 500:
|
||||||
|
miscService.handleError(ErrorMessages.INTERNAL_SERVER_ERROR,[]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
miscService.handleError(ErrorMessages.CONNECTION_ERROR,[]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private addToken(request: HttpRequest<any>, token: string) {
|
||||||
|
return request.clone({
|
||||||
|
setHeaders: {
|
||||||
|
'Authorization': `Bearer ${token}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { finalize } from 'rxjs/operators';
|
||||||
|
import { LoadingService } from '../services/loading.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class LoadingInterceptor implements HttpInterceptor {
|
||||||
|
constructor(private loadingService: LoadingService) {}
|
||||||
|
|
||||||
|
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||||
|
this.loadingService.showLoader();
|
||||||
|
|
||||||
|
return next.handle(request).pipe(
|
||||||
|
finalize(() => this.loadingService.hideLoader())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,192 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { CONSTANTS } from '../../utils/app.constants';
|
||||||
|
import { HttpClient, HttpErrorResponse, HttpHeaders, HttpParams } from '@angular/common/http';
|
||||||
|
import { MiscService } from './misc.service';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { environment } from '../../../environments/environment';
|
||||||
|
import { APP_URL_KEY } from '../../utils/enums';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class HttpService {
|
||||||
|
|
||||||
|
API_PATH = environment.apiPath.get(APP_URL_KEY.API_PATH)
|
||||||
|
|
||||||
|
constructor(private translateService: TranslateService,
|
||||||
|
private miscService: MiscService, private http: HttpClient
|
||||||
|
) { }
|
||||||
|
|
||||||
|
getRequest(url: string, queryParams?: HttpParams, pathParams?: any, showLoader = true, options?: any) {
|
||||||
|
|
||||||
|
const custId: any = localStorage.getItem("USERKEY");
|
||||||
|
let headers = new HttpHeaders().set("Content-Type", "application/json");
|
||||||
|
|
||||||
|
const authorization = "Bearer " + localStorage.getItem('token');
|
||||||
|
headers = headers.set("Authorization", authorization);
|
||||||
|
headers = headers.set("cmpUserId", custId);
|
||||||
|
let apiUrl = this.API_PATH + url;
|
||||||
|
this.miscService.showLoader();
|
||||||
|
apiUrl = this.replaceParamsWithValues(apiUrl, pathParams);
|
||||||
|
|
||||||
|
try {
|
||||||
|
let response = this.http.get(apiUrl, { headers: headers });
|
||||||
|
|
||||||
|
if (!(response instanceof HttpErrorResponse)) {
|
||||||
|
if (showLoader) {
|
||||||
|
this.miscService.hideLoader();
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.miscService.handleError(this.translateService.instant('ServerError'));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
postRequest(url: string, data?: any, pathParams?: any, isMultipart = false, showLoader = true) {
|
||||||
|
const custId = localStorage.getItem("USERKEY");
|
||||||
|
let headers = new HttpHeaders().set("Content-Type", "application/json");
|
||||||
|
let apiUrl = this.API_PATH + url;
|
||||||
|
this.miscService.showLoader();
|
||||||
|
headers = headers.set("Authorization", "Bearer " + localStorage.getItem('token'));
|
||||||
|
if (custId != null) {
|
||||||
|
headers = headers.set("cmpUserId", custId);
|
||||||
|
}
|
||||||
|
apiUrl = this.replaceParamsWithValues(apiUrl, pathParams);
|
||||||
|
|
||||||
|
let formData = data;
|
||||||
|
formData = this.setCommonParams(formData);
|
||||||
|
if (isMultipart) {
|
||||||
|
formData = this.convertToFormData(data);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
let response = this.http.post(apiUrl, formData, { headers: headers });
|
||||||
|
|
||||||
|
if (!(response instanceof HttpErrorResponse)) {
|
||||||
|
if (showLoader) {
|
||||||
|
this.miscService.hideLoader();
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.miscService.handleError(this.translateService.instant('ServerError'));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
putRequest(url: string, data: any, pathParams?: any, isMultipart = false, showLoader = true) {
|
||||||
|
const custId: any = localStorage.getItem("USERKEY");
|
||||||
|
let headers = new HttpHeaders().set("Content-Type", "application/json");
|
||||||
|
headers = headers.set("cmpUserId", custId);
|
||||||
|
headers = headers.set("Authorization", "Bearer " + localStorage.getItem('token'));
|
||||||
|
let apiUrl = this.API_PATH + url;
|
||||||
|
apiUrl = this.replaceParamsWithValues(apiUrl, pathParams);
|
||||||
|
this.miscService.showLoader();
|
||||||
|
let formData = data;
|
||||||
|
formData = this.setCommonParams(formData);
|
||||||
|
if (isMultipart) {
|
||||||
|
formData = this.convertToFormData(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
let response = this.http.put(apiUrl, formData, { headers: headers });
|
||||||
|
|
||||||
|
if (!(response instanceof HttpErrorResponse)) {
|
||||||
|
if (showLoader) {
|
||||||
|
this.miscService.hideLoader();
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.miscService.handleError(this.translateService.instant('ServerError'));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
deleteRequest(url: any, data: any, pathParams?: any, isMultipart = false, showLoader = true) {
|
||||||
|
const custId: any = localStorage.getItem("USERKEY");
|
||||||
|
let apiUrl = this.API_PATH + url;
|
||||||
|
let headers = new HttpHeaders().set("Content-Type", "application/json");
|
||||||
|
headers = headers.set("Authorization", "Bearer " + localStorage.getItem('token'));
|
||||||
|
headers = headers.set("cmpUserId", custId);
|
||||||
|
apiUrl = this.replaceParamsWithValues(apiUrl, pathParams);
|
||||||
|
|
||||||
|
this.miscService.showLoader();
|
||||||
|
let formData = data;
|
||||||
|
formData = this.setCommonParams(formData);
|
||||||
|
if (isMultipart) {
|
||||||
|
formData = this.convertToFormData(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
let response = this.http.delete(apiUrl, { headers: headers, body: formData });
|
||||||
|
|
||||||
|
if (!(response instanceof HttpErrorResponse)) {
|
||||||
|
if (showLoader) {
|
||||||
|
this.miscService.hideLoader();
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.miscService.handleError(this.translateService.instant('ServerError'));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addQueryParamsToUrl(url: any, queryParams: any) {
|
||||||
|
if (queryParams && Object.keys(queryParams).length > 0) {
|
||||||
|
let toReturn = url + '?';
|
||||||
|
Object.keys(queryParams).forEach((key, index, arr) => {
|
||||||
|
toReturn += `${key}=${queryParams[key]}`;
|
||||||
|
toReturn += index === arr.length - 1 ? '' : '&';
|
||||||
|
});
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
convertToFormData(data: any) {
|
||||||
|
const formData = new FormData();
|
||||||
|
Object.keys(data).forEach((k) => {
|
||||||
|
formData.append(k, data[k]);
|
||||||
|
});
|
||||||
|
return formData;
|
||||||
|
}
|
||||||
|
replaceParamsWithValues(url: any, data: any) {
|
||||||
|
data = data ?? {};
|
||||||
|
data['porOrgacode'] = CONSTANTS.POR_ORGACODE;
|
||||||
|
if (data && Object.keys(data).length > 0) {
|
||||||
|
Object.keys(data).forEach((k) => {
|
||||||
|
url = url.replace(`{${k}}`, data[k]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
setCommonParams(data: any = {}) {
|
||||||
|
data = data ?? {};
|
||||||
|
data['porOrgacode'] = CONSTANTS.POR_ORGACODE;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { BehaviorSubject } from 'rxjs';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class LoadingService {
|
||||||
|
|
||||||
|
private loadingSubject = new BehaviorSubject<boolean>(false);
|
||||||
|
loading$ = this.loadingSubject.asObservable();
|
||||||
|
|
||||||
|
showLoader() {
|
||||||
|
this.loadingSubject.next(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
hideLoader() {
|
||||||
|
this.loadingSubject.next(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { MessageService } from '../../services/message.service';
|
||||||
|
import { SpinnerService } from '../../services/spinner.service';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class MiscService {
|
||||||
|
|
||||||
|
constructor(private message: MessageService, private spinnerService: SpinnerService,private translateService: TranslateService,) { }
|
||||||
|
|
||||||
|
showLoader(): void {
|
||||||
|
this.spinnerService.IsBusy(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
hideLoader(): void {
|
||||||
|
this.spinnerService.IsBusy(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSuccess(message: string): void {
|
||||||
|
this.message.Success(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleError(errorMessage: string, argumentValues: string[] = []): void {
|
||||||
|
const translatedErrorMessage = this.translateService.instant(errorMessage, { value1: argumentValues[0], value2: argumentValues[1], value3: argumentValues[2] });
|
||||||
|
this.message.Error(translatedErrorMessage);
|
||||||
|
}
|
||||||
|
getErrorMessageTranslation(key: string) {
|
||||||
|
return this.getTranslation(`${key}`);
|
||||||
|
}
|
||||||
|
getTranslation(key: string, defaultLabel?: string): string {
|
||||||
|
if (key == null || key === "" || key == undefined) {
|
||||||
|
return defaultLabel ? defaultLabel : "";
|
||||||
|
}
|
||||||
|
let translated = this.translateService.instant(String(key));
|
||||||
|
if (translated == key || translated == "") {
|
||||||
|
if (defaultLabel && defaultLabel.length > 0) {
|
||||||
|
return defaultLabel;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return translated;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
import { isPlatformBrowser } from '@angular/common';
|
||||||
|
import { Inject, Injectable, PLATFORM_ID } from '@angular/core';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class StorageService {
|
||||||
|
|
||||||
|
private isBrowser: boolean = false;
|
||||||
|
|
||||||
|
constructor(@Inject(PLATFORM_ID) platformId: object) {
|
||||||
|
this.isBrowser = isPlatformBrowser(platformId);
|
||||||
|
}
|
||||||
|
|
||||||
|
getItem(key: string): string | null {
|
||||||
|
if (this.isBrowser) {
|
||||||
|
return localStorage.getItem(key);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
setItem(key: string, value: string) {
|
||||||
|
if (this.isBrowser) {
|
||||||
|
localStorage.setItem(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
if (this.isBrowser) {
|
||||||
|
localStorage.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,207 @@
|
|||||||
|
<div id="layout-wrapper">
|
||||||
|
<div class="inner-pg-sp">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="d-sm-flex align-items-center justify-content-between navbar-header p-0">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="col-xl-12 mt-4">
|
||||||
|
<div class="card border">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-section">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="card-body mt-2 p-0">
|
||||||
|
<div class="card mb-0 mt-2">
|
||||||
|
<div
|
||||||
|
class="card-header font-edit-13-child d-flex justify-content-between align-items-center">
|
||||||
|
{{'smsLogger' | translate}}
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form>
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label for="fromDate" class="text-nowrap">
|
||||||
|
{{ 'fromDate' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
class="password-wrapper position-relative w-100">
|
||||||
|
<div
|
||||||
|
class="d-flex flex-row align-items-stretch">
|
||||||
|
<input type="date" id="fromDate"
|
||||||
|
class="form-control"
|
||||||
|
appNoWhitespaces />
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- <div class="text-danger">
|
||||||
|
{{ 'requiredField' | translate }}
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-start gap-2">
|
||||||
|
<label for="toDate" class="text-nowrap mt-2">
|
||||||
|
{{ 'toDate' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
class="password-wrapper position-relative w-100">
|
||||||
|
|
||||||
|
<input id="toDate" type="date" class="form-control"
|
||||||
|
maxlength="500"
|
||||||
|
appNoWhitespaces rows="3" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6 ms-auto text-end">
|
||||||
|
<button
|
||||||
|
class="btn btn-primary waves-effect waves-light">{{'findLogs'
|
||||||
|
| translate}}</button>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="col-xl-12 mt-4">
|
||||||
|
<div class="card border">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-section">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="card-body mt-2 p-0">
|
||||||
|
<div class="card mb-0 mt-2">
|
||||||
|
<div
|
||||||
|
class="card-header font-edit-13-child d-flex justify-content-between align-items-center">
|
||||||
|
{{'smsLoggerDetails' | translate}}
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<div class="search-box">
|
||||||
|
<input type="text" class="form-control form-control-sm"
|
||||||
|
placeholder="{{ 'search' | translate }}">
|
||||||
|
<i class="fas fa-search search-icon"></i>
|
||||||
|
</div>
|
||||||
|
<i class="materialdesignicons">
|
||||||
|
<ng-container *ngIf="renewalDataExpanded; else collapsedIcon">
|
||||||
|
<i class="dripicons-chevron-up float-end"></i>
|
||||||
|
</ng-container>
|
||||||
|
<ng-template #collapsedIcon>
|
||||||
|
<i class="dripicons-chevron-down float-end"></i>
|
||||||
|
</ng-template>
|
||||||
|
</i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table mb-0 border">
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th>{{'smsTrackingID' | translate}}</th>
|
||||||
|
<th>{{'smsMessage' | translate}}</th>
|
||||||
|
<th>{{'smsNo' | translate}}</th>
|
||||||
|
<th>{{'smsOrgaCode' | translate}}</th>
|
||||||
|
<th>{{'smsDate' | translate}}</th>
|
||||||
|
<th>{{'smsStatus' | translate}}</th>
|
||||||
|
<th>{{'action' | translate}}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<div
|
||||||
|
class="d-flex justify-content-center gap-2">
|
||||||
|
|
||||||
|
<button class="btn btn-info btn-sm"
|
||||||
|
title="View">
|
||||||
|
<i class="mdi mdi-eye-outline"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button class="btn btn-secondary btn-sm"
|
||||||
|
title="Edit">
|
||||||
|
<i class="fas fa-pen"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
|
||||||
|
<button class="btn btn-danger btn-sm"
|
||||||
|
title="Delete">
|
||||||
|
<i class="fas fa-trash-alt"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div
|
||||||
|
class="d-flex justify-content-between align-items-center mt-3">
|
||||||
|
<div class="form-group mb-0">
|
||||||
|
<ng-select class="form-select-sm"
|
||||||
|
[items]="pageSizeOptions" bindLabel="label"
|
||||||
|
bindValue="value" [(ngModel)]="itemsPerPage"
|
||||||
|
[searchable]="false" [clearable]="false"
|
||||||
|
[dropdownPosition]="'top'">
|
||||||
|
</ng-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-muted">
|
||||||
|
{{ 'page' | translate }} {{ 'of' | translate }} ({{
|
||||||
|
'totalItems' | translate }})
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="btn-group">
|
||||||
|
<button
|
||||||
|
class="btn btn-primary waves-effect waves-light">
|
||||||
|
{{ 'previous' | translate }}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-primary waves-effect waves-light">
|
||||||
|
{{ 'next' | translate }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { SmsBankingComponent } from './sms-banking.component';
|
||||||
|
|
||||||
|
describe('SmsBankingComponent', () => {
|
||||||
|
let component: SmsBankingComponent;
|
||||||
|
let fixture: ComponentFixture<SmsBankingComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [SmsBankingComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(SmsBankingComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { NgSelectModule } from '@ng-select/ng-select';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { pageSizeOptions } from '../utils/app.constants';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
|
||||||
|
selector: 'app-sms-banking',
|
||||||
|
imports: [TranslateModule, ReactiveFormsModule, NgSelectModule, CommonModule, FormsModule],
|
||||||
|
templateUrl: './sms-banking.component.html',
|
||||||
|
styleUrl: './sms-banking.component.scss'
|
||||||
|
})
|
||||||
|
export class SmsBankingComponent {
|
||||||
|
currentPage: number = 1;
|
||||||
|
pageSizeOptions = pageSizeOptions
|
||||||
|
renewalDataExpanded: boolean = true
|
||||||
|
itemsPerPage: number = 5;
|
||||||
|
searchText: any;
|
||||||
|
}
|
||||||
@ -0,0 +1,280 @@
|
|||||||
|
<div id="layout-wrapper">
|
||||||
|
<div class="inner-pg-sp">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="d-sm-flex align-items-center justify-content-between navbar-header p-0">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="col-xl-12 mt-4">
|
||||||
|
<div class="card border">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-section">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="card-body mt-2 p-0">
|
||||||
|
<div class="card mb-0 mt-2">
|
||||||
|
<div
|
||||||
|
class="card-header font-edit-13-child d-flex justify-content-between align-items-center">
|
||||||
|
<span *ngIf="!selectedGateway"></span>
|
||||||
|
<span *ngIf="selectedGateway">{{(selectedGateway === selectedGatewayType.SYRIATEL ? 'syriatelCredentials' : (selectedGateway === selectedGatewayType.TWILIO ? 'twilioCredentials' : (selectedGateway === selectedGatewayType.JAZZ ? 'jazzCredentials' : ''))) | translate}}</span>
|
||||||
|
<select class="form-select"style="min-width: 200px; width: auto;" [(ngModel)]="selectedGateway">
|
||||||
|
<option value="">{{'SMSGatewaySelect' | translate}}</option>
|
||||||
|
<option [value]="selectedGatewayType.SYRIATEL">{{'SMSGatewaySyriatel' | translate}}</option>
|
||||||
|
<option [value]="selectedGatewayType.TWILIO">{{'SMSGatewayTwillio' | translate}}</option>
|
||||||
|
<option [value]="selectedGatewayType.JAZZ">{{'SMSGatewayJazz' | translate}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form *ngIf="selectedGateway==='Jazz' || selectedGateway==='Twilio'">
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label for="accountSID" class="text-nowrap">
|
||||||
|
{{ 'accountSID' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="password-wrapper position-relative w-100">
|
||||||
|
<div class="d-flex flex-row align-items-stretch">
|
||||||
|
<input type="text" id="accountSID"
|
||||||
|
class="form-control"
|
||||||
|
|
||||||
|
placeholder="{{ 'accountSID' | translate }}" appNoWhitespaces
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- <div class="text-danger">
|
||||||
|
{{ 'requiredField' | translate }}
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-start gap-2">
|
||||||
|
<label for="authToken"
|
||||||
|
class="text-nowrap mt-2">
|
||||||
|
{{ 'authToken' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="password-wrapper position-relative w-100">
|
||||||
|
|
||||||
|
<input id="authToken" class="form-control" autocomplete="new-password" maxlength="500"
|
||||||
|
placeholder="{{ 'authToken' | translate }}" appNoWhitespaces rows="3" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label for="fromNumber" class="text-nowrap">
|
||||||
|
{{ 'fromNumber' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="password-wrapper position-relative w-100">
|
||||||
|
<input id="fromNumber" class="form-control"
|
||||||
|
placeholder="{{ 'fromNumber' | translate }}" appNoWhitespaces />
|
||||||
|
|
||||||
|
|
||||||
|
<!-- <div class="text-danger">
|
||||||
|
<div>
|
||||||
|
{{ 'requiredField' | translate }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ 'expiryBeforeRenewal' | translate }}
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label class="text-nowrap">
|
||||||
|
{{ 'notificationType' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="w-100 d-flex gap-3">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="notificationType" id="message" value="Message">
|
||||||
|
<label class="form-check-label" for="message">
|
||||||
|
{{ 'message' | translate }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="notificationType" id="template" value="Template">
|
||||||
|
<label class="form-check-label" for="template">
|
||||||
|
{{ 'template' | translate }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label class="text-nowrap">
|
||||||
|
{{ 'language' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="w-100 d-flex gap-3">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="language" id="languageArabic" value="Arabic">
|
||||||
|
<label class="form-check-label" for="languageArabic">
|
||||||
|
{{ 'arabic' | translate }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="language" id="languageEnglish" value="English">
|
||||||
|
<label class="form-check-label" for="languageEnglish">
|
||||||
|
{{ 'english' | translate }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6 ms-auto text-end">
|
||||||
|
<button
|
||||||
|
class="btn btn-primary waves-effect waves-light"
|
||||||
|
|
||||||
|
>{{'save' | translate}}</button>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</form>
|
||||||
|
<form *ngIf="selectedGateway==='Syriatel'">
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label for="userName" class="text-nowrap">
|
||||||
|
{{ 'userName' | translate }}<span class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="password-wrapper position-relative w-100">
|
||||||
|
<div class="d-flex flex-row align-items-stretch">
|
||||||
|
<input type="text" id="userName" class="form-control" placeholder="{{ 'userNamePlaceHolder' | translate }}"
|
||||||
|
appNoWhitespaces />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label for="senderName" class="text-nowrap">
|
||||||
|
{{ 'senderName' | translate }}<span class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="password-wrapper position-relative w-100">
|
||||||
|
<input type="text" id="senderName" class="form-control" placeholder="{{ 'senderNamePlaceHolder' | translate }}"
|
||||||
|
appNoWhitespaces />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-start gap-2">
|
||||||
|
<label for="password" class="text-nowrap mt-2">
|
||||||
|
{{ 'password' | translate }}<span class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="password-wrapper position-relative w-100">
|
||||||
|
<input type="password" id="password" class="form-control" autocomplete="new-password"
|
||||||
|
maxlength="500" placeholder="{{ 'passwordPlaceholder' | translate }}" appNoWhitespaces />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label class="text-nowrap">
|
||||||
|
{{ 'notificationType' | translate }}<span class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="w-100 d-flex gap-3">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="notificationType" id="message"
|
||||||
|
value="Message">
|
||||||
|
<label class="form-check-label" for="message">
|
||||||
|
{{ 'message' | translate }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="notificationType" id="template"
|
||||||
|
value="Template">
|
||||||
|
<label class="form-check-label" for="template">
|
||||||
|
{{ 'template' | translate }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label class="text-nowrap">
|
||||||
|
{{ 'language' | translate }}<span class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="w-100 d-flex gap-3">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="language" id="languageArabic" value="Arabic">
|
||||||
|
<label class="form-check-label" for="languageArabic">
|
||||||
|
{{ 'arabic' | translate }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="radio" name="language" id="languageEnglish"
|
||||||
|
value="English">
|
||||||
|
<label class="form-check-label" for="languageEnglish">
|
||||||
|
{{ 'english' | translate }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6 ms-auto text-end">
|
||||||
|
<button class="btn btn-primary waves-effect waves-light">
|
||||||
|
{{'save' | translate}}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { SmsGatewayComponent } from './sms-gateway.component';
|
||||||
|
|
||||||
|
describe('SmsGatewayComponent', () => {
|
||||||
|
let component: SmsGatewayComponent;
|
||||||
|
let fixture: ComponentFixture<SmsGatewayComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [SmsGatewayComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(SmsGatewayComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { NgSelectComponent } from '@ng-select/ng-select';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { selectedGatewayType } from '../utils/enums';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-sms-gateway',
|
||||||
|
imports: [TranslateModule, FormsModule, CommonModule],
|
||||||
|
templateUrl: './sms-gateway.component.html',
|
||||||
|
styleUrl: './sms-gateway.component.scss'
|
||||||
|
})
|
||||||
|
export class SmsGatewayComponent {
|
||||||
|
selectedGateway: string = '';
|
||||||
|
selectedGatewayType = selectedGatewayType
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,122 @@
|
|||||||
|
<div id="layout-wrapper">
|
||||||
|
<div class="inner-pg-sp">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="d-sm-flex align-items-center justify-content-between navbar-header p-0">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="col-xl-12 mt-4">
|
||||||
|
<div class="card border">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-section">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="card-body mt-2 p-0">
|
||||||
|
<div class="card mb-0 mt-2">
|
||||||
|
<div
|
||||||
|
class="card-header font-edit-13-child d-flex justify-content-between align-items-center">
|
||||||
|
{{'changePassword' | translate}}
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form>
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label for="oldPassword" class="text-nowrap">
|
||||||
|
{{ 'oldPassword' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="password-wrapper position-relative w-100">
|
||||||
|
<div class="d-flex flex-row align-items-stretch">
|
||||||
|
<input type="text" id="oldPassword"
|
||||||
|
class="form-control"
|
||||||
|
type="{{passwordType}}"
|
||||||
|
placeholder="{{ 'oldPassword' | translate }}" appNoWhitespaces
|
||||||
|
/>
|
||||||
|
<app-password-hide-show #psh class="password-eye align-items-stretch" [showPassword]="true" (onEyeClick)="togglePasswordType()"></app-password-hide-show>
|
||||||
|
</div>
|
||||||
|
<!-- <div class="text-danger">
|
||||||
|
{{ 'requiredField' | translate }}
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-start gap-2">
|
||||||
|
<label for="enterNewPassword"
|
||||||
|
class="text-nowrap mt-2">
|
||||||
|
{{ 'enterNewPassword' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="password-wrapper position-relative w-100">
|
||||||
|
|
||||||
|
<input id="enterNewPassword"
|
||||||
|
class="form-control"
|
||||||
|
type="{{passwordType1}}"
|
||||||
|
maxlength="500"
|
||||||
|
placeholder="{{ 'enterNewPassword' | translate }}" appNoWhitespaces
|
||||||
|
rows="3" />
|
||||||
|
<app-password-hide-show #psh1 class="password-eye align-items-stretch" [showPassword]="true" (onEyeClick)="togglePasswordType1()"></app-password-hide-show>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label for="confirmPassword" class="text-nowrap">
|
||||||
|
{{ 'confirmPassword' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="password-wrapper position-relative w-100">
|
||||||
|
|
||||||
|
<input id="confirmPassword"
|
||||||
|
class="form-control"
|
||||||
|
type="{{passwordType2}}"
|
||||||
|
maxlength="500"
|
||||||
|
placeholder="{{ 'confirmPassword' | translate }}" appNoWhitespaces
|
||||||
|
rows="3" />
|
||||||
|
<app-password-hide-show #psh2 class="password-eye align-items-stretch" [showPassword]="true" (onEyeClick)="togglePasswordType2()"></app-password-hide-show>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6 ms-auto text-end">
|
||||||
|
<button
|
||||||
|
class="btn btn-primary waves-effect waves-light"
|
||||||
|
|
||||||
|
>{{'save' | translate}}</button>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ChangePasswordComponent } from './change-password.component';
|
||||||
|
|
||||||
|
describe('ChangePasswordComponent', () => {
|
||||||
|
let component: ChangePasswordComponent;
|
||||||
|
let fixture: ComponentFixture<ChangePasswordComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [ChangePasswordComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(ChangePasswordComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { Component, ViewChild } from '@angular/core';
|
||||||
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { PasswordHideShowComponent } from '../../shared/components/password-hide-show/password-hide-show.component';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-change-password',
|
||||||
|
imports: [TranslateModule, FormsModule, ReactiveFormsModule, CommonModule, PasswordHideShowComponent],
|
||||||
|
templateUrl: './change-password.component.html',
|
||||||
|
styleUrl: './change-password.component.scss'
|
||||||
|
})
|
||||||
|
export class ChangePasswordComponent {
|
||||||
|
passwordType: string = 'password';
|
||||||
|
passwordType1: string = 'password';
|
||||||
|
passwordType2: string = 'password';
|
||||||
|
|
||||||
|
@ViewChild('psh') passwordHideShow?: PasswordHideShowComponent;
|
||||||
|
@ViewChild('psh1') passwordHideShow1 ?: PasswordHideShowComponent;
|
||||||
|
@ViewChild('psh2') passwordHideShow2 ?: PasswordHideShowComponent;
|
||||||
|
|
||||||
|
|
||||||
|
togglePasswordType() {
|
||||||
|
this.passwordType = this.passwordHideShow?.showPassword ? 'password' : 'text';
|
||||||
|
}
|
||||||
|
togglePasswordType1() {
|
||||||
|
this.passwordType1 = this.passwordHideShow1?.showPassword ? 'password' : 'text';
|
||||||
|
}
|
||||||
|
togglePasswordType2() {
|
||||||
|
this.passwordType2 = this.passwordHideShow2?.showPassword ? 'password' : 'text';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,128 @@
|
|||||||
|
<div id="layout-wrapper">
|
||||||
|
<div class="inner-pg-sp">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="d-sm-flex align-items-center justify-content-between navbar-header p-0">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="col-xl-12 mt-4">
|
||||||
|
<div class="card border">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-section">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="card-body mt-2 p-0">
|
||||||
|
<div class="card mb-0 mt-2">
|
||||||
|
<div
|
||||||
|
class="card-header font-edit-13-child d-flex justify-content-between align-items-center">
|
||||||
|
{{'resetPassword' | translate}}
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form >
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label for="userID" class="text-nowrap">
|
||||||
|
{{ 'userID' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="password-wrapper position-relative w-100">
|
||||||
|
<div class="d-flex flex-row align-items-stretch">
|
||||||
|
<input type="text" id="userID"
|
||||||
|
class="form-control"
|
||||||
|
|
||||||
|
placeholder="{{ 'userID' | translate }}" appNoWhitespaces
|
||||||
|
|
||||||
|
/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- <div class="text-danger">
|
||||||
|
{{ 'requiredField' | translate }}
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-start gap-2">
|
||||||
|
<label for="enterNewPassword"
|
||||||
|
class="text-nowrap mt-2">
|
||||||
|
{{ 'enterNewPassword' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="password-wrapper position-relative w-100">
|
||||||
|
|
||||||
|
<input id="enterNewPassword"
|
||||||
|
class="form-control"
|
||||||
|
autocomplete="new-password"
|
||||||
|
type="{{passwordType1}}"
|
||||||
|
maxlength="500"
|
||||||
|
placeholder="{{ 'enterNewPassword' | translate }}" appNoWhitespaces
|
||||||
|
rows="3" />
|
||||||
|
<app-password-hide-show #psh1 class="password-eye align-items-stretch" [showPassword]="true" (onEyeClick)="togglePasswordType1()"></app-password-hide-show>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label for="confirmPassword" class="text-nowrap">
|
||||||
|
{{ 'confirmPassword' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="password-wrapper position-relative w-100">
|
||||||
|
<input id="confirmPassword"
|
||||||
|
class="form-control"
|
||||||
|
type="{{passwordType2}}"
|
||||||
|
|
||||||
|
placeholder="{{ 'confirmPassword' | translate }}" appNoWhitespaces/>
|
||||||
|
<app-password-hide-show class="password-eye align-items-stretch" #psh2 [showPassword]="true" (onEyeClick)="togglePasswordType2()"></app-password-hide-show>
|
||||||
|
<!-- <div class="text-danger">
|
||||||
|
<div>
|
||||||
|
{{ 'requiredField' | translate }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ 'expiryBeforeRenewal' | translate }}
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6 ms-auto text-end">
|
||||||
|
<button
|
||||||
|
class="btn btn-primary waves-effect waves-light"
|
||||||
|
|
||||||
|
>{{'save' | translate}}</button>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ResetPasswordComponent } from './reset-password.component';
|
||||||
|
|
||||||
|
describe('ResetPasswordComponent', () => {
|
||||||
|
let component: ResetPasswordComponent;
|
||||||
|
let fixture: ComponentFixture<ResetPasswordComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [ResetPasswordComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(ResetPasswordComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
import { Component, ViewChild } from '@angular/core';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { PasswordHideShowComponent } from '../../shared/components/password-hide-show/password-hide-show.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-reset-password',
|
||||||
|
imports: [TranslateModule, PasswordHideShowComponent],
|
||||||
|
templateUrl: './reset-password.component.html',
|
||||||
|
styleUrl: './reset-password.component.scss'
|
||||||
|
})
|
||||||
|
export class ResetPasswordComponent {
|
||||||
|
passwordType1: string = 'password';
|
||||||
|
passwordType2: string = 'password';
|
||||||
|
|
||||||
|
|
||||||
|
@ViewChild('psh1') passwordHideShow1 ?: PasswordHideShowComponent;
|
||||||
|
@ViewChild('psh2') passwordHideShow2 ?: PasswordHideShowComponent;
|
||||||
|
|
||||||
|
|
||||||
|
togglePasswordType1() {
|
||||||
|
this.passwordType1 = this.passwordHideShow1?.showPassword ? 'password' : 'text';
|
||||||
|
}
|
||||||
|
togglePasswordType2() {
|
||||||
|
this.passwordType2 = this.passwordHideShow2?.showPassword ? 'password' : 'text';
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,226 @@
|
|||||||
|
<div id="layout-wrapper">
|
||||||
|
<div class="inner-pg-sp">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="d-sm-flex align-items-center justify-content-between navbar-header p-0">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="col-xl-12 mt-4">
|
||||||
|
<div class="card border">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-section">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="card-body mt-2 p-0">
|
||||||
|
<div class="card mb-0 mt-2">
|
||||||
|
<div
|
||||||
|
class="card-header font-edit-13-child d-flex justify-content-between align-items-center">
|
||||||
|
{{'setupUser' | translate}}
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form>
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label for="userID" class="text-nowrap">
|
||||||
|
{{ 'userID' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="password-wrapper position-relative w-100">
|
||||||
|
<div class="d-flex flex-row align-items-stretch">
|
||||||
|
<input type="text" id="userID"
|
||||||
|
class="form-control"
|
||||||
|
|
||||||
|
placeholder="{{ 'userID' | translate }}" appNoWhitespaces
|
||||||
|
/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- <div class="text-danger">
|
||||||
|
{{ 'requiredField' | translate }}
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-start gap-2">
|
||||||
|
<label for="name"
|
||||||
|
class="text-nowrap mt-2">
|
||||||
|
{{ 'name' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="password-wrapper position-relative w-100">
|
||||||
|
|
||||||
|
<input id="name"
|
||||||
|
class="form-control"
|
||||||
|
|
||||||
|
maxlength="500"
|
||||||
|
placeholder="{{ 'userName' | translate }}" appNoWhitespaces
|
||||||
|
rows="3" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label for="phoneNumber" class="text-nowrap">
|
||||||
|
{{ 'phoneNumber' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="password-wrapper position-relative w-100">
|
||||||
|
<input id="phoneNumber"
|
||||||
|
class="form-control"
|
||||||
|
|
||||||
|
placeholder="{{ 'userContactNumber' | translate }}" appNoWhitespaces/>
|
||||||
|
|
||||||
|
<!-- <div class="text-danger">
|
||||||
|
<div>
|
||||||
|
{{ 'requiredField' | translate }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{ 'expiryBeforeRenewal' | translate }}
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6 ms-auto text-end">
|
||||||
|
<button
|
||||||
|
class="btn btn-primary waves-effect waves-light"
|
||||||
|
|
||||||
|
>{{'save' | translate}}</button>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="col-xl-12 mt-4">
|
||||||
|
<div class="card border">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-section">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="card-body mt-2 p-0">
|
||||||
|
<div class="card mb-0 mt-2">
|
||||||
|
<div class="card-header font-edit-13-child d-flex justify-content-between align-items-center">
|
||||||
|
{{'SetupUserDetails' | translate}}
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<div class="search-box">
|
||||||
|
<input type="text" class="form-control form-control-sm"
|
||||||
|
placeholder="{{ 'search' | translate }}">
|
||||||
|
<i class="fas fa-search search-icon"></i>
|
||||||
|
</div>
|
||||||
|
<i class="materialdesignicons">
|
||||||
|
<ng-container *ngIf="renewalDataExpanded; else collapsedIcon">
|
||||||
|
<i class="dripicons-chevron-up float-end"></i>
|
||||||
|
</ng-container>
|
||||||
|
<ng-template #collapsedIcon>
|
||||||
|
<i class="dripicons-chevron-down float-end"></i>
|
||||||
|
</ng-template>
|
||||||
|
</i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table mb-0 border">
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th>{{'userID' | translate}}</th>
|
||||||
|
<th>{{'Name' | translate}}</th>
|
||||||
|
<th>{{'phoneNumber' | translate}}</th>
|
||||||
|
<th>{{'action' | translate}}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<div class="d-flex justify-content-center gap-2">
|
||||||
|
|
||||||
|
<button class="btn btn-info btn-sm" title="View">
|
||||||
|
<i class="mdi mdi-eye-outline"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button class="btn btn-secondary btn-sm" title="Edit">
|
||||||
|
<i class="fas fa-pen"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
|
||||||
|
<button class="btn btn-danger btn-sm" title="Delete">
|
||||||
|
<i class="fas fa-trash-alt"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="d-flex justify-content-between align-items-center mt-3">
|
||||||
|
<div class="form-group mb-0">
|
||||||
|
<ng-select class="form-select-sm"
|
||||||
|
[items]="pageSizeOptions"
|
||||||
|
bindLabel="label"
|
||||||
|
bindValue="value"
|
||||||
|
[(ngModel)]="itemsPerPage"
|
||||||
|
[searchable]="false"
|
||||||
|
[clearable]="false"
|
||||||
|
[dropdownPosition]="'top'">
|
||||||
|
</ng-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-muted">
|
||||||
|
{{ 'page' | translate }} {{ 'of' | translate }} ({{ 'totalItems' | translate }})
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="btn-group">
|
||||||
|
<button class="btn btn-primary waves-effect waves-light">
|
||||||
|
{{ 'previous' | translate }}
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-primary waves-effect waves-light">
|
||||||
|
{{ 'next' | translate }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { SetupUserComponent } from './setup-user.component';
|
||||||
|
|
||||||
|
describe('SetupUserComponent', () => {
|
||||||
|
let component: SetupUserComponent;
|
||||||
|
let fixture: ComponentFixture<SetupUserComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [SetupUserComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(SetupUserComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { NgSelectModule } from '@ng-select/ng-select';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { pageSizeOptions } from '../../utils/app.constants';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-setup-user',
|
||||||
|
standalone: true,
|
||||||
|
imports: [TranslateModule, ReactiveFormsModule, FormsModule, CommonModule, NgSelectModule],
|
||||||
|
templateUrl: './setup-user.component.html',
|
||||||
|
styleUrl: './setup-user.component.scss'
|
||||||
|
})
|
||||||
|
export class SetupUserComponent {
|
||||||
|
allItems: any[] = [];
|
||||||
|
currentPage: number = 1;
|
||||||
|
pageSizeOptions = pageSizeOptions
|
||||||
|
itemsPerPage: number = 5;
|
||||||
|
searchText: any;
|
||||||
|
renewalDataExpanded: boolean = true;
|
||||||
|
|
||||||
|
nextPage() {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
|
||||||
|
previousPage() {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
|
||||||
|
totalPages() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleCard(arg0: string) {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit() {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,294 @@
|
|||||||
|
<div id="layout-wrapper">
|
||||||
|
<div class="inner-pg-sp">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="d-sm-flex align-items-center justify-content-between navbar-header p-0">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="col-xl-12 mt-4">
|
||||||
|
<div class="card border">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-section">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="card-body mt-2 p-0">
|
||||||
|
<div class="card mb-0 mt-2">
|
||||||
|
<div
|
||||||
|
class="card-header font-edit-13-child d-flex justify-content-between align-items-center">
|
||||||
|
{{'thirdPartyRegistration' | translate}}
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form>
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label for="renewalDate" class="text-nowrap">
|
||||||
|
{{ 'ThirdPartyID' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="d-flex flex-column w-100">
|
||||||
|
<input type="text" id="renewalDate"
|
||||||
|
class="form-control"
|
||||||
|
placeholder="{{ 'ThirdPartyID' | translate }}" />
|
||||||
|
<!-- <div *ngIf="vacForm.get('renewalDate')?.invalid && (vacForm.get('renewalDate')?.touched || isSubmitted)"
|
||||||
|
class="text-danger">
|
||||||
|
{{ 'requiredField' | translate }}
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-start gap-2">
|
||||||
|
<label for="renewalRemarks"
|
||||||
|
class="text-nowrap mt-2">
|
||||||
|
{{ 'name' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="d-flex flex-column w-100">
|
||||||
|
<input type="text" id="renewalDate"
|
||||||
|
class="form-control"
|
||||||
|
placeholder="{{ 'thirdPartyNamePlaceholder' | translate }}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label for="renewalDate" class="text-nowrap">
|
||||||
|
{{ 'Email' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="d-flex flex-column w-100">
|
||||||
|
<input type="text" id="renewalDate"
|
||||||
|
class="form-control"
|
||||||
|
placeholder="{{ 'Email' | translate }}" />
|
||||||
|
<!-- <div *ngIf="vacForm.get('renewalDate')?.invalid && (vacForm.get('renewalDate')?.touched || isSubmitted)"
|
||||||
|
class="text-danger">
|
||||||
|
{{ 'requiredField' | translate }}
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-start gap-2">
|
||||||
|
<label for="renewalRemarks"
|
||||||
|
class="text-nowrap mt-2">
|
||||||
|
{{ 'Address' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="d-flex flex-column w-100">
|
||||||
|
<input type="text" id="renewalDate"
|
||||||
|
class="form-control"
|
||||||
|
placeholder="{{ 'Address' | translate }}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<label for="renewalDate" class="text-nowrap">
|
||||||
|
{{ 'phoneNumber' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="d-flex flex-column w-100">
|
||||||
|
<input type="text" id="renewalDate"
|
||||||
|
class="form-control"
|
||||||
|
placeholder="{{ 'phoneNumberPlaceholder' | translate }}" />
|
||||||
|
<!-- <div *ngIf="vacForm.get('renewalDate')?.invalid && (vacForm.get('renewalDate')?.touched || isSubmitted)"
|
||||||
|
class="text-danger">
|
||||||
|
{{ 'requiredField' | translate }}
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-start gap-2">
|
||||||
|
<label for="renewalRemarks"
|
||||||
|
class="text-nowrap mt-2">
|
||||||
|
{{ 'NewNoOfAccounts' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div class="d-flex flex-column w-100">
|
||||||
|
<input type="text" id="renewalDate"
|
||||||
|
class="form-control"
|
||||||
|
placeholder="{{ 'newNoOfAccountsPlaceholder' | translate }}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="d-flex align-items-start gap-2">
|
||||||
|
<label for="renewalRemarks"
|
||||||
|
class="text-nowrap mt-2">
|
||||||
|
{{ 'password' | translate }}<span
|
||||||
|
class="mandatory">*</span>
|
||||||
|
</label>
|
||||||
|
<div
|
||||||
|
class="password-wrapper position-relative w-100">
|
||||||
|
<input [type]="passwordType"
|
||||||
|
autocomplete="new-password"
|
||||||
|
class="form-control pe-5"
|
||||||
|
placeholder="{{ 'password' | translate }}">
|
||||||
|
|
||||||
|
<app-password-hide-show class="password-eye"
|
||||||
|
[showPassword]="true"
|
||||||
|
(onEyeClick)="togglePasswordType()">
|
||||||
|
</app-password-hide-show>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="row g-3 mb-3">
|
||||||
|
<div class="col-md-6 ms-auto text-end">
|
||||||
|
<button
|
||||||
|
class="btn btn-primary waves-effect waves-light">{{'save'
|
||||||
|
|
|
||||||
|
translate}}</button>
|
||||||
|
<!-- <button
|
||||||
|
class="btn btn-primary waves-effect waves-light"
|
||||||
|
>{{'update' |
|
||||||
|
translate}}</button>
|
||||||
|
<button
|
||||||
|
class="btn btn-primary waves-effect waves-light"
|
||||||
|
>{{'cancel' |
|
||||||
|
translate}}</button> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="col-xl-12 mt-4">
|
||||||
|
<div class="card border">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-section">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="card-body mt-2 p-0">
|
||||||
|
<div class="card mb-0 mt-2">
|
||||||
|
<div
|
||||||
|
class="card-header font-edit-13-child d-flex justify-content-between align-items-center">
|
||||||
|
{{'thirdPartyRegistrationDetails' | translate}}
|
||||||
|
<div class="d-flex align-items-center gap-2">
|
||||||
|
<div class="search-box">
|
||||||
|
<input type="text" class="form-control form-control-sm"
|
||||||
|
[(ngModel)]="searchText"
|
||||||
|
placeholder="{{ 'search' | translate }}">
|
||||||
|
<i class="fas fa-search search-icon"></i>
|
||||||
|
</div>
|
||||||
|
<i class="materialdesignicons">
|
||||||
|
<ng-container *ngIf="renewalDataExpanded; else collapsedIcon">
|
||||||
|
<i class="dripicons-chevron-up float-end"></i>
|
||||||
|
</ng-container>
|
||||||
|
<ng-template #collapsedIcon>
|
||||||
|
<i class="dripicons-chevron-down float-end"></i>
|
||||||
|
</ng-template>
|
||||||
|
</i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table mb-0 border">
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th>{{'ThirdPartyID' | translate}}</th>
|
||||||
|
<th>{{'name' | translate}}</th>
|
||||||
|
<th>{{'Email' | translate}}</th>
|
||||||
|
<th>{{'Address' | translate}}</th>
|
||||||
|
<th>{{'phoneNumber' | translate}}</th>
|
||||||
|
<th>{{'TotalNoOfAccounts' | translate}}</th>
|
||||||
|
<th>{{'action' | translate}}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td>
|
||||||
|
<div
|
||||||
|
class="d-flex justify-content-center gap-2">
|
||||||
|
|
||||||
|
<button class="btn btn-info btn-sm"
|
||||||
|
title="View">
|
||||||
|
<i class="mdi mdi-eye-outline"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button class="btn btn-secondary btn-sm"
|
||||||
|
title="Edit">
|
||||||
|
<i class="fas fa-pen"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
|
||||||
|
<button class="btn btn-danger btn-sm"
|
||||||
|
title="Delete">
|
||||||
|
<i class="fas fa-trash-alt"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div class="d-flex justify-content-between align-items-center mt-3">
|
||||||
|
<div class="form-group mb-0">
|
||||||
|
<ng-select class="form-select-sm" [items]="pageSizeOptions" bindLabel="label" bindValue="value"
|
||||||
|
[(ngModel)]="itemsPerPage" [searchable]="false" [clearable]="false">
|
||||||
|
</ng-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-muted">
|
||||||
|
{{'page' | translate}} {{'of' | translate}} ( {{'totalItems' | translate}})
|
||||||
|
</div>
|
||||||
|
<!-- <div class="text-muted">
|
||||||
|
{{'no_record' | translate}}
|
||||||
|
</div>
|
||||||
|
<div class="text-muted">
|
||||||
|
{{'page' | translate}} {{'of' | translate}} ( {{'record' | translate}})
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
<div class="btn-group">
|
||||||
|
<button class="btn btn-primary waves-effect waves-light">
|
||||||
|
{{'previous' | translate}}
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-primary waves-effect waves-light">
|
||||||
|
{{'next' | translate}}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue