Compare commits
4 Commits
master
...
User_Role_
Author | SHA1 | Date | |
---|---|---|---|
14eb61b75d | |||
ec91f9ee4f | |||
e65b1f5870 | |||
69a0b38b41 |
@ -30,6 +30,31 @@
|
||||
"allowedCommonJsDependencies": ["chart.js", "js-sha256"],
|
||||
"assets": ["src/favicon.ico", "src/assets"],
|
||||
"styles": [
|
||||
{
|
||||
"input": "node_modules/primeng/resources/themes/saga-blue/theme.css",
|
||||
"inject": true,
|
||||
"bundleName": "saga-blue"
|
||||
},
|
||||
{
|
||||
"input": "node_modules/primeflex/themes/primeone-dark.css",
|
||||
"inject": true,
|
||||
"bundleName": "primeone-dark"
|
||||
},
|
||||
{
|
||||
"input": "node_modules/primeng/resources/primeng.min.css",
|
||||
"inject": true,
|
||||
"bundleName": "primeng.min"
|
||||
},
|
||||
{
|
||||
"input": "node_modules/primeicons/primeicons.css",
|
||||
"inject": true,
|
||||
"bundleName": "primeicons"
|
||||
},
|
||||
{
|
||||
"input": "node_modules/primeflex/primeflex.min.css",
|
||||
"inject": true,
|
||||
"bundleName": "primeflex.min"
|
||||
},
|
||||
{
|
||||
"input": "node_modules/@volo/ngx-lepton-x.lite/assets/css/bootstrap-dim.css",
|
||||
"inject": false,
|
||||
|
@ -20,7 +20,7 @@
|
||||
"@abp/ng.setting-management": "~9.0.2",
|
||||
"@abp/ng.tenant-management": "~9.0.2",
|
||||
"@abp/ng.theme.lepton-x": "~4.0.3",
|
||||
"@abp/ng.theme.shared": "~9.0.2",
|
||||
"@abp/ng.theme.shared": "^9.0.4",
|
||||
"@angular/animations": "~18.1.0",
|
||||
"@angular/common": "~18.1.0",
|
||||
"@angular/compiler": "~18.1.0",
|
||||
@ -30,7 +30,11 @@
|
||||
"@angular/platform-browser": "~18.1.0",
|
||||
"@angular/platform-browser-dynamic": "~18.1.0",
|
||||
"@angular/router": "~18.1.0",
|
||||
"@swimlane/ngx-datatable": "^20.1.0",
|
||||
"bootstrap-icons": "~1.8.0",
|
||||
"primeflex": "^3.3.1",
|
||||
"primeicons": "^6.0.1",
|
||||
"primeng": "^17.18.0",
|
||||
"rxjs": "~7.8.0",
|
||||
"tslib": "^2.0.0",
|
||||
"zone.js": "~0.14.0"
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { CustomUsersComponent } from './modules/custom-identity/custom-users/custom-users.component';
|
||||
import { CustomRolesComponent } from './modules/custom-identity/custom-roles/custom-roles.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
@ -11,10 +13,12 @@ const routes: Routes = [
|
||||
path: 'account',
|
||||
loadChildren: () => import('@abp/ng.account').then(m => m.AccountModule.forLazy()),
|
||||
},
|
||||
{
|
||||
path: 'identity',
|
||||
loadChildren: () => import('@abp/ng.identity').then(m => m.IdentityModule.forLazy()),
|
||||
},
|
||||
{ path: 'identity/users', component: CustomUsersComponent },
|
||||
{ path: 'identity/roles', component: CustomRolesComponent },
|
||||
// {
|
||||
// path: 'identity',
|
||||
// loadChildren: () => import('@abp/ng.identity').then(m => m.IdentityModule.forLazy()),
|
||||
// },
|
||||
{
|
||||
path: 'tenant-management',
|
||||
loadChildren: () =>
|
||||
@ -25,12 +29,38 @@ const routes: Routes = [
|
||||
loadChildren: () =>
|
||||
import('@abp/ng.setting-management').then(m => m.SettingManagementModule.forLazy()),
|
||||
},
|
||||
{ path: 'appointment/appointment-calendar',
|
||||
loadChildren: () =>
|
||||
import('./appointment/appointment-calendar/appointment-calendar.module').then(m => m.AppointmentCalendarModule) },
|
||||
{ path: 'appointment/view-appointment', loadChildren: () => import('./appointment/view-appointment/view-appointment.module').then(m => m.ViewAppointmentModule) },
|
||||
{ path: 'appointment/book-appointment', loadChildren: () => import('./appointment/book-appointment/book-appointment.module').then(m => m.BookAppointmentModule) },
|
||||
{ path: 'appointment/edit-appointment', loadChildren: () => import('./appointment/edit-appointment/edit-appointment.module').then(m => m.EditAppointmentModule) },
|
||||
{
|
||||
path: 'appointment/appointment-calendar',
|
||||
loadChildren: () =>
|
||||
import('./appointment/appointment-calendar/appointment-calendar.module').then(
|
||||
m => m.AppointmentCalendarModule
|
||||
),
|
||||
},
|
||||
{
|
||||
path: 'appointment/view-appointment',
|
||||
loadChildren: () =>
|
||||
import('./appointment/view-appointment/view-appointment.module').then(
|
||||
m => m.ViewAppointmentModule
|
||||
),
|
||||
},
|
||||
{
|
||||
path: 'appointment/book-appointment',
|
||||
loadChildren: () =>
|
||||
import('./appointment/book-appointment/book-appointment.module').then(
|
||||
m => m.BookAppointmentModule
|
||||
),
|
||||
},
|
||||
{
|
||||
path: 'appointment/edit-appointment',
|
||||
loadChildren: () =>
|
||||
import('./appointment/edit-appointment/edit-appointment.module').then(
|
||||
m => m.EditAppointmentModule
|
||||
),
|
||||
},
|
||||
{
|
||||
path: 'patients',
|
||||
loadChildren: () => import('./patients/patients.module').then(m => m.PatientsModule),
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
@ -0,0 +1,23 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { IdentityModule } from '@abp/ng.identity';
|
||||
import { TableModule } from 'primeng/table';
|
||||
import { ButtonModule } from 'primeng/button';
|
||||
import { CustomRolesComponent } from './custom-roles/custom-roles.component';
|
||||
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
imports: [
|
||||
CommonModule,
|
||||
IdentityModule,
|
||||
TableModule,
|
||||
ButtonModule,
|
||||
CustomRolesComponent
|
||||
],
|
||||
exports:[
|
||||
CustomRolesComponent
|
||||
]
|
||||
})
|
||||
export class CustomIdentityModule { }
|
@ -0,0 +1,125 @@
|
||||
<abp-page [title]="'AbpIdentity::Roles' | abpLocalization" [toolbar]="data.items">
|
||||
<div id="identity-roles-wrapper" class="card">
|
||||
<div class="card-body">
|
||||
<!-- <abp-extensible-table
|
||||
[data]="data.items"
|
||||
[recordsTotal]="data.totalCount"
|
||||
[list]="list"
|
||||
></abp-extensible-table> -->
|
||||
<div class="flex justify-content-between align-items-center mb-3">
|
||||
<button pButton icon="pi pi-plus" label="Add Roles" class="p-button-success" (click)="add()"></button>
|
||||
</div>
|
||||
<p-table [value]="data.items" [paginator]="true" [rows]="5" responsiveLayout="scroll">
|
||||
<ng-template pTemplate="header">
|
||||
<tr>
|
||||
<th pSortableColumn="name">Role name <p-sortIcon field="name"></p-sortIcon></th>
|
||||
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</ng-template>
|
||||
|
||||
<ng-template pTemplate="body" let-role>
|
||||
<tr>
|
||||
<td>{{ role.name }}</td>
|
||||
|
||||
|
||||
<td>
|
||||
<button pButton icon="pi pi-pencil" class="p-button-text p-button-primary" (click)="edit(role.id)"></button>
|
||||
<button pButton icon="pi pi-trash" class="p-button-text p-button-danger" (click)="delete(role.id,role.name)"></button>
|
||||
<button pButton icon="pi pi-lock" class="p-button-text p-button-success" (click)="openPermissionsModal(role.name)"></button>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
</p-table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<abp-modal [(visible)]="isModalVisible" [busy]="modalBusy">
|
||||
<ng-template #abpHeader>
|
||||
<h3>{{ (selected?.id ? 'AbpIdentity::Edit' : 'AbpIdentity::NewRole') | abpLocalization }}</h3>
|
||||
</ng-template>
|
||||
|
||||
<!-- <ng-template #abpBody>
|
||||
<form [formGroup]="form" (ngSubmit)="save()" validateOnSubmit>
|
||||
<abp-extensible-form [selectedRecord]="selected"></abp-extensible-form>
|
||||
</form>
|
||||
</ng-template> -->
|
||||
|
||||
<ng-template #abpBody>
|
||||
<form #roleForm="ngForm" (ngSubmit)="save()" validateOnSubmit>
|
||||
<!-- Name Field -->
|
||||
<div class="form-group">
|
||||
<label for="name">Name</label>
|
||||
<input
|
||||
id="name"
|
||||
type="text"
|
||||
class="form-control"
|
||||
[(ngModel)]="selected.name"
|
||||
name="name"
|
||||
required
|
||||
#nameCtrl="ngModel"
|
||||
/>
|
||||
<small class="text-danger" *ngIf="nameCtrl.invalid && nameCtrl.touched">Name is required</small>
|
||||
</div>
|
||||
|
||||
<!-- Is Default Checkbox -->
|
||||
<div class="form-check">
|
||||
<input
|
||||
id="isDefault"
|
||||
type="checkbox"
|
||||
class="form-check-input"
|
||||
[(ngModel)]="selected.isDefault"
|
||||
name="isDefault"
|
||||
/>
|
||||
<label for="isDefault" class="form-check-label">Default</label>
|
||||
</div>
|
||||
|
||||
<!-- Is Public Checkbox -->
|
||||
<div class="form-check">
|
||||
<input
|
||||
id="isPublic"
|
||||
type="checkbox"
|
||||
class="form-check-input"
|
||||
[(ngModel)]="selected.isPublic"
|
||||
name="isPublic"
|
||||
/>
|
||||
<label for="isPublic" class="form-check-label">Public</label>
|
||||
</div>
|
||||
<br>
|
||||
<abp-button iconClass="fa fa-check" [disabled]="roleForm.invalid" (click)="save()">{{
|
||||
'AbpIdentity::Save' | abpLocalization
|
||||
}}</abp-button>
|
||||
</form>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #abpFooter>
|
||||
<button type="button" class="btn btn-outline-primary" abpClose>
|
||||
{{ 'AbpIdentity::Cancel' | abpLocalization }}
|
||||
</button>
|
||||
<!-- <abp-button iconClass="fa fa-check" [disabled]="roleForm?.invalid" (click)="save()">{{
|
||||
'AbpIdentity::Save' | abpLocalization
|
||||
}}</abp-button> -->
|
||||
</ng-template>
|
||||
</abp-modal>
|
||||
|
||||
<abp-permission-management
|
||||
#abpPermissionManagement="abpPermissionManagement"
|
||||
*abpReplaceableTemplate="
|
||||
{
|
||||
inputs: {
|
||||
providerName: { value: 'R' },
|
||||
providerKey: { value: providerKey },
|
||||
visible: { value: visiblePermissions, twoWay: true },
|
||||
hideBadges: { value: true }
|
||||
},
|
||||
outputs: { visibleChange: onVisiblePermissionChange },
|
||||
componentKey: permissionManagementKey
|
||||
};
|
||||
let init = initTemplate
|
||||
"
|
||||
(abpInit)="init(abpPermissionManagement)"
|
||||
>
|
||||
</abp-permission-management>
|
||||
</abp-page>
|
||||
|
@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CustomRolesComponent } from './custom-roles.component';
|
||||
|
||||
describe('CustomRolesComponent', () => {
|
||||
let component: CustomRolesComponent;
|
||||
let fixture: ComponentFixture<CustomRolesComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [CustomRolesComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(CustomRolesComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,213 @@
|
||||
import {
|
||||
ExtensibleModule,
|
||||
EXTENSIONS_IDENTIFIER,
|
||||
FormPropData,
|
||||
generateFormFromProps,
|
||||
} from '@abp/ng.components/extensible';
|
||||
import { PageModule } from '@abp/ng.components/page';
|
||||
import {
|
||||
CoreModule,
|
||||
ListResultDto,
|
||||
ListService,
|
||||
LocalizationModule,
|
||||
PagedAndSortedResultRequestDto,
|
||||
PagedResultDto,
|
||||
} from '@abp/ng.core';
|
||||
import { IdentityRoleCreateDto, IdentityRoleDto, IdentityRoleService, IdentityRoleUpdateDto } from '@abp/ng.identity/proxy';
|
||||
import {
|
||||
ThemeSharedModule,
|
||||
ConfirmationService,
|
||||
ToasterService,
|
||||
Confirmation,
|
||||
} from '@abp/ng.theme.shared';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component, inject, Injector, OnInit } from '@angular/core';
|
||||
import { FormControl, FormGroup, FormsModule, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { ButtonModule } from 'primeng/button';
|
||||
import { TableModule } from 'primeng/table';
|
||||
import { finalize } from 'rxjs';
|
||||
import { ePermissionManagementComponents } from '@abp/ng.permission-management';
|
||||
import { NgxDatatableModule } from '@swimlane/ngx-datatable';
|
||||
import { eIdentityComponents } from '@abp/ng.identity';
|
||||
import { PermissionManagementModule } from '@abp/ng.permission-management';
|
||||
import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { MenuItem } from 'primeng/api';
|
||||
import { Dropdown, DropdownModule } from 'primeng/dropdown';
|
||||
|
||||
@Component({
|
||||
selector: 'app-custom-roles',
|
||||
standalone: true,
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
TableModule,
|
||||
ButtonModule,
|
||||
PageModule,
|
||||
LocalizationModule,
|
||||
ThemeSharedModule,
|
||||
NgxDatatableModule,
|
||||
ExtensibleModule,
|
||||
PermissionManagementModule,
|
||||
CoreModule,
|
||||
NgbNavModule,
|
||||
DropdownModule
|
||||
],
|
||||
templateUrl: './custom-roles.component.html',
|
||||
providers: [
|
||||
ListService,
|
||||
{
|
||||
provide: EXTENSIONS_IDENTIFIER,
|
||||
useValue: eIdentityComponents.Roles,
|
||||
},
|
||||
],
|
||||
styleUrl: './custom-roles.component.scss',
|
||||
})
|
||||
export class CustomRolesComponent implements OnInit {
|
||||
protected readonly list = inject(ListService<PagedAndSortedResultRequestDto>);
|
||||
protected readonly confirmationService = inject(ConfirmationService);
|
||||
protected readonly toasterService = inject(ToasterService);
|
||||
private readonly injector = inject(Injector);
|
||||
protected readonly service = inject(IdentityRoleService);
|
||||
|
||||
data: PagedResultDto<IdentityRoleDto> = { items: [], totalCount: 0 };
|
||||
|
||||
form!: UntypedFormGroup;
|
||||
|
||||
selected?: IdentityRoleDto;
|
||||
|
||||
isModalVisible!: boolean;
|
||||
|
||||
visiblePermissions = false;
|
||||
|
||||
providerKey?: string;
|
||||
|
||||
modalBusy = false;
|
||||
|
||||
permissionManagementKey = ePermissionManagementComponents.PermissionManagement;
|
||||
|
||||
onVisiblePermissionChange = (event: boolean) => {
|
||||
this.visiblePermissions = event;
|
||||
};
|
||||
|
||||
ngOnInit() {
|
||||
|
||||
this.hookToQuery();
|
||||
}
|
||||
|
||||
// buildForm() {
|
||||
// const data = new FormPropData(this.injector, this.selected);
|
||||
// this.form = generateFormFromProps(data);
|
||||
// }
|
||||
buildForm() {
|
||||
this.form = new FormGroup({
|
||||
name: new FormControl(this.selected?.name || '', Validators.required),
|
||||
isDefault: new FormControl(this.selected?.isDefault || false),
|
||||
isPublic: new FormControl(this.selected?.isPublic || false)
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
openModal() {
|
||||
this.buildForm();
|
||||
this.isModalVisible = true;
|
||||
}
|
||||
|
||||
add() {
|
||||
debugger
|
||||
// this.selected = {} as IdentityRoleDto;
|
||||
// this.openModal();
|
||||
this.selected = { name: '', isDefault: false, isPublic: false } as IdentityRoleDto;
|
||||
this.isModalVisible = true;
|
||||
}
|
||||
|
||||
edit(id: string) {
|
||||
debugger
|
||||
// this.service.get(id).subscribe(res => {
|
||||
// this.selected = res;
|
||||
// this.openModal();
|
||||
// });
|
||||
this.service.get(id).subscribe(res => {
|
||||
this.selected = res;
|
||||
this.isModalVisible = true;
|
||||
});
|
||||
}
|
||||
|
||||
// save() {
|
||||
// debugger
|
||||
// if (!this.form.valid) return;
|
||||
// this.modalBusy = true;
|
||||
|
||||
// const { id } = this.selected || {};
|
||||
// (id
|
||||
// ? this.service.update(id, { ...this.selected, ...this.form.value })
|
||||
// : this.service.create(this.form.value)
|
||||
// )
|
||||
// .pipe(finalize(() => (this.modalBusy = false)))
|
||||
// .subscribe(() => {
|
||||
// this.isModalVisible = false;
|
||||
// this.toasterService.success('AbpUi::SavedSuccessfully');
|
||||
// this.list.get();
|
||||
// });
|
||||
// }
|
||||
save() {
|
||||
debugger
|
||||
if (!this.selected?.name) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.modalBusy = true;
|
||||
|
||||
const { id, name, isDefault, isPublic, concurrencyStamp } = this.selected;
|
||||
|
||||
const roleDto = {
|
||||
name,
|
||||
isDefault,
|
||||
isPublic,
|
||||
concurrencyStamp
|
||||
};
|
||||
|
||||
const saveObservable = id
|
||||
? this.service.update(id, roleDto) // Update call
|
||||
: this.service.create(roleDto); // Create call
|
||||
|
||||
saveObservable
|
||||
.pipe(finalize(() => (this.modalBusy = false)))
|
||||
.subscribe(() => {
|
||||
this.isModalVisible = false;
|
||||
this.toasterService.success('AbpUi::SavedSuccessfully');
|
||||
this.list.get();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
delete(id: string, name: string) {
|
||||
this.confirmationService
|
||||
.warn('AbpIdentity::RoleDeletionConfirmationMessage', 'AbpIdentity::AreYouSure', {
|
||||
messageLocalizationParams: [name],
|
||||
})
|
||||
.subscribe((status: Confirmation.Status) => {
|
||||
if (status === Confirmation.Status.confirm) {
|
||||
this.toasterService.success('AbpUi::DeletedSuccessfully');
|
||||
this.service.delete(id).subscribe(() => this.list.get());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private hookToQuery() {
|
||||
this.list.hookToQuery(query => this.service.getList(query)).subscribe(res => (this.data = res));
|
||||
}
|
||||
|
||||
openPermissionsModal(providerKey: string) {
|
||||
this.providerKey = providerKey;
|
||||
setTimeout(() => {
|
||||
this.visiblePermissions = true;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
sort(data: any) {
|
||||
const { prop, dir } = data.sorts[0];
|
||||
this.list.sortKey = prop;
|
||||
this.list.sortOrder = dir;
|
||||
}
|
||||
}
|
@ -0,0 +1,332 @@
|
||||
<!-- <div>
|
||||
<h3>Total Users: {{ data.totalCount }}</h3>
|
||||
<ul>
|
||||
<li *ngFor="let user of data.items">
|
||||
<strong>{{ user.userName }}</strong> ({{ user.email }})
|
||||
</li>
|
||||
</ul>
|
||||
</div> -->
|
||||
|
||||
<abp-page [title]="'AbpIdentity::Users' | abpLocalization" [toolbar]="data.items">
|
||||
<div id="identity-roles-wrapper" class="card">
|
||||
<div class="card-body">
|
||||
<div id="data-tables-table-filter" class="data-tables-filter mb-3">
|
||||
<div class="flex justify-content-between align-items-center mb-3">
|
||||
<button
|
||||
pButton
|
||||
icon="pi pi-plus"
|
||||
label="Add User"
|
||||
class="p-button-success"
|
||||
(click)="add()"
|
||||
></button>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<input
|
||||
type="search"
|
||||
class="form-control"
|
||||
[placeholder]="'AbpUi::PagerSearch' | abpLocalization"
|
||||
[(ngModel)]="list.filter"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<abp-extensible-table
|
||||
|
||||
[data]="data.items"
|
||||
[recordsTotal]="data.totalCount"
|
||||
[list]="list"
|
||||
|
||||
></abp-extensible-table> -->
|
||||
<p-table
|
||||
[value]="data.items"
|
||||
[tableStyle]="{ 'min-width': '60rem' }"
|
||||
[paginator]="true"
|
||||
[rows]="5"
|
||||
responsiveLayout="scroll"
|
||||
>
|
||||
<ng-template pTemplate="header">
|
||||
<tr>
|
||||
<th pSortableColumn="userName">Username <p-sortIcon field="userName"></p-sortIcon></th>
|
||||
<th pSortableColumn="name">First Name <p-sortIcon field="name"></p-sortIcon></th>
|
||||
<th pSortableColumn="surname">Last Name <p-sortIcon field="surname"></p-sortIcon></th>
|
||||
<th pSortableColumn="email">Email <p-sortIcon field="email"></p-sortIcon></th>
|
||||
<th pSortableColumn="Phone">Phone No <p-sortIcon field="Phone"></p-sortIcon></th>
|
||||
<th>Status</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</ng-template>
|
||||
|
||||
<ng-template pTemplate="body" let-user>
|
||||
<tr>
|
||||
<td>{{ user.userName }}</td>
|
||||
<td>{{ user.name }}</td>
|
||||
<td>{{ user.surname }}</td>
|
||||
<td>{{ user.email }}</td>
|
||||
<td>{{ user.phoneNumber }}</td>
|
||||
<td>
|
||||
<p-tag
|
||||
[value]="user.isActive ? 'Active' : 'Inactive'"
|
||||
[severity]="user.isActive ? 'success' : 'danger'"
|
||||
></p-tag>
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group" dropdown placement="bottom left" container="body">
|
||||
<p-splitButton
|
||||
label="Actions"
|
||||
icon="pi pi-cog"
|
||||
class="p-button-sm p-button-primary"
|
||||
[model]="actionItems"
|
||||
(onClick)="editUser(user.id)"
|
||||
>
|
||||
</p-splitButton>
|
||||
</div>
|
||||
<!-- <button
|
||||
pButton
|
||||
icon="pi pi-pencil"
|
||||
class="p-button-text p-button-primary"
|
||||
(click)="edit(user.id)"
|
||||
></button>
|
||||
<button
|
||||
pButton
|
||||
icon="pi pi-trash"
|
||||
class="p-button-text p-button-danger"
|
||||
(click)="delete(user.id, user.userName)"
|
||||
></button>
|
||||
<button
|
||||
pButton
|
||||
icon="pi pi-lock"
|
||||
class="p-button-text p-button-success"
|
||||
(click)="openPermissionsModal(user.id, user.userName)"
|
||||
></button> -->
|
||||
<!-- <div class="btn-group" dropdown placement="bottom left" container="body">
|
||||
<button
|
||||
id="dropdownButton"
|
||||
type="button"
|
||||
class="btn btn-primary btn-sm dropdown-toggle"
|
||||
dropdownToggle
|
||||
aria-controls="dropdownMenu"
|
||||
(click)="toggleDropdown()"
|
||||
>
|
||||
<i class="fa fa-cog"></i>
|
||||
<span class="caret"></span>
|
||||
Actions
|
||||
</button>
|
||||
<ul
|
||||
id="dropdownMenu"
|
||||
#dropdownMenu
|
||||
class="dropdown-menu"
|
||||
role="menu"
|
||||
aria-labelledby="dropdownButton"
|
||||
|
||||
>
|
||||
<li role="menuitem" tabindex="0">
|
||||
<a
|
||||
#firstDropdownItem
|
||||
class="dropdown-item"
|
||||
href="javascript:;"
|
||||
(click)="edit(user.id)"
|
||||
>
|
||||
Edit
|
||||
</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</div> -->
|
||||
</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
</p-table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<abp-modal [(visible)]="isModalVisible" [busy]="modalBusy">
|
||||
<ng-template #abpHeader>
|
||||
<h3>
|
||||
{{ (selected?.id ? 'AbpIdentity::EditUser' : 'AbpIdentity::NewUser') | abpLocalization }}
|
||||
</h3>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #abpBody>
|
||||
<form #userForm="ngForm" (ngSubmit)="save(userForm)">
|
||||
<!-- User Information Tab -->
|
||||
<ul ngbNav #nav="ngbNav" class="nav-tabs">
|
||||
<li ngbNavItem>
|
||||
<a ngbNavLink>{{ 'AbpIdentity::UserInformations' | abpLocalization }}</a>
|
||||
<ng-template ngbNavContent>
|
||||
<div class="form-group">
|
||||
<label for="userName">{{ 'User Name' | abpLocalization }}</label>
|
||||
<input
|
||||
id="userName"
|
||||
type="text"
|
||||
class="form-control"
|
||||
[(ngModel)]="selected.userName"
|
||||
name="userName"
|
||||
required
|
||||
#userName="ngModel"
|
||||
/>
|
||||
<div *ngIf="userName.invalid && userName.touched" class="text-danger">
|
||||
User Name is required
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Password -->
|
||||
<div class="form-group" *ngIf="!selected.id">
|
||||
<label for="password">Password</label>
|
||||
<input
|
||||
id="password"
|
||||
type="password"
|
||||
class="form-control"
|
||||
[(ngModel)]="password"
|
||||
name="password"
|
||||
required
|
||||
#passwordField="ngModel"
|
||||
/>
|
||||
<div *ngIf="passwordField.invalid && passwordField.touched" class="text-danger">
|
||||
Password is required
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Name -->
|
||||
<div class="form-group">
|
||||
<label for="name">{{ 'Name' | abpLocalization }}</label>
|
||||
<input
|
||||
id="name"
|
||||
type="text"
|
||||
class="form-control"
|
||||
[(ngModel)]="selected.name"
|
||||
name="name"
|
||||
#name="ngModel"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Surname -->
|
||||
<div class="form-group">
|
||||
<label for="surname">{{ 'Surname' | abpLocalization }}</label>
|
||||
<input
|
||||
id="surname"
|
||||
type="text"
|
||||
class="form-control"
|
||||
[(ngModel)]="selected.surname"
|
||||
name="surname"
|
||||
#surname="ngModel"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Email -->
|
||||
<div class="form-group">
|
||||
<label for="email">{{ 'Email' | abpLocalization }}</label>
|
||||
<input
|
||||
id="email"
|
||||
type="email"
|
||||
class="form-control"
|
||||
[(ngModel)]="selected.email"
|
||||
name="email"
|
||||
required
|
||||
#email="ngModel"
|
||||
/>
|
||||
<div *ngIf="email.invalid && email.touched" class="text-danger">
|
||||
Valid Email is required
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Phone Number -->
|
||||
<div class="form-group">
|
||||
<label for="phoneNumber">{{ 'Phone Number' | abpLocalization }}</label>
|
||||
<input
|
||||
id="phoneNumber"
|
||||
type="text"
|
||||
class="form-control"
|
||||
[(ngModel)]="selected.phoneNumber"
|
||||
name="phoneNumber"
|
||||
#phoneNumber="ngModel"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Active Account (Checkbox) -->
|
||||
<div class="form-check">
|
||||
<input
|
||||
id="isActive"
|
||||
type="checkbox"
|
||||
class="form-check-input"
|
||||
[(ngModel)]="selected.isActive"
|
||||
name="isActive"
|
||||
/>
|
||||
<label for="isActive" class="form-check-label">{{
|
||||
'Active' | abpLocalization
|
||||
}}</label>
|
||||
</div>
|
||||
|
||||
<!-- Lockout Enabled (Checkbox) -->
|
||||
<div class="form-check">
|
||||
<input
|
||||
id="lockoutEnabled"
|
||||
type="checkbox"
|
||||
class="form-check-input"
|
||||
[(ngModel)]="selected.lockoutEnabled"
|
||||
name="lockoutEnabled"
|
||||
/>
|
||||
<label for="lockoutEnabled" class="form-check-label">{{
|
||||
'Lockout Enabled' | abpLocalization
|
||||
}}</label>
|
||||
</div>
|
||||
</ng-template>
|
||||
</li>
|
||||
|
||||
<!-- Roles Tab -->
|
||||
<li ngbNavItem>
|
||||
<a ngbNavLink>{{ 'AbpIdentity::Roles' | abpLocalization }}</a>
|
||||
<ng-template ngbNavContent>
|
||||
<div *ngFor="let role of roles; let i = index">
|
||||
<div class="form-check mb-2">
|
||||
<label class="form-check-label">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="form-check-input"
|
||||
[(ngModel)]="role.selected"
|
||||
name="role-{{ i }}"
|
||||
/>
|
||||
{{ role.name }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="mt-2 fade-in-top" [ngbNavOutlet]="nav"></div>
|
||||
|
||||
<div class="mt-3">
|
||||
<button type="submit" class="btn btn-primary" [disabled]="userForm.invalid">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #abpFooter>
|
||||
<button type="button" class="btn btn-outline-primary" abpClose>
|
||||
{{ 'AbpIdentity::Cancel' | abpLocalization }}
|
||||
</button>
|
||||
<!-- <abp-button iconClass="fa fa-check" [disabled]="form?.invalid" (click)="save()">{{
|
||||
'AbpIdentity::Save' | abpLocalization
|
||||
}}</abp-button> -->
|
||||
</ng-template>
|
||||
</abp-modal>
|
||||
|
||||
<abp-permission-management
|
||||
#abpPermissionManagement="abpPermissionManagement"
|
||||
*abpReplaceableTemplate="
|
||||
{
|
||||
inputs: {
|
||||
providerName: { value: 'U' },
|
||||
providerKey: { value: providerKey },
|
||||
visible: { value: visiblePermissions, twoWay: true }
|
||||
},
|
||||
outputs: { visibleChange: onVisiblePermissionChange },
|
||||
componentKey: permissionManagementKey
|
||||
};
|
||||
let init = initTemplate
|
||||
"
|
||||
[entityDisplayName]="entityDisplayName"
|
||||
(abpInit)="init(abpPermissionManagement)"
|
||||
>
|
||||
</abp-permission-management>
|
||||
</abp-page>
|
@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CustomUsersComponent } from './custom-users.component';
|
||||
|
||||
describe('CustomUsersComponent', () => {
|
||||
let component: CustomUsersComponent;
|
||||
let fixture: ComponentFixture<CustomUsersComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [CustomUsersComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(CustomUsersComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,395 @@
|
||||
import {
|
||||
FormPropData,
|
||||
EXTENSIONS_IDENTIFIER,
|
||||
generateFormFromProps,
|
||||
ExtensibleModule,
|
||||
} from '@abp/ng.components/extensible';
|
||||
import { PageModule } from '@abp/ng.components/page';
|
||||
import {
|
||||
CoreModule,
|
||||
ListResultDto,
|
||||
ListService,
|
||||
LocalizationModule,
|
||||
PagedResultDto,
|
||||
} from '@abp/ng.core';
|
||||
import { eIdentityComponents } from '@abp/ng.identity';
|
||||
import {
|
||||
GetIdentityUsersInput,
|
||||
IdentityRoleDto,
|
||||
IdentityUserDto,
|
||||
IdentityUserService,
|
||||
IdentityUserUpdateDto,
|
||||
} from '@abp/ng.identity/proxy';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import {
|
||||
Component,
|
||||
ElementRef,
|
||||
HostListener,
|
||||
inject,
|
||||
Injector,
|
||||
OnInit,
|
||||
TemplateRef,
|
||||
TrackByFunction,
|
||||
ViewChild,
|
||||
} from '@angular/core';
|
||||
import {
|
||||
AbstractControl,
|
||||
FormsModule,
|
||||
NgForm,
|
||||
UntypedFormArray,
|
||||
UntypedFormBuilder,
|
||||
UntypedFormGroup,
|
||||
} from '@angular/forms';
|
||||
import { ButtonModule } from 'primeng/button';
|
||||
import { TableModule } from 'primeng/table';
|
||||
import {
|
||||
Confirmation,
|
||||
eFormComponets,
|
||||
ThemeSharedModule,
|
||||
ToasterService,
|
||||
ConfirmationService,
|
||||
} from '@abp/ng.theme.shared';
|
||||
import { finalize, switchMap, tap } from 'rxjs';
|
||||
import {
|
||||
ePermissionManagementComponents,
|
||||
PermissionManagementModule,
|
||||
} from '@abp/ng.permission-management';
|
||||
import { NgxDatatableModule } from '@swimlane/ngx-datatable';
|
||||
import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { PaginatorModule } from 'primeng/paginator';
|
||||
import { TagModule } from 'primeng/tag'; // For active/inactive status
|
||||
import { SplitButtonModule } from 'primeng/splitbutton';
|
||||
|
||||
@Component({
|
||||
selector: 'app-custom-users',
|
||||
standalone: true,
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
TableModule,
|
||||
ButtonModule,
|
||||
PageModule,
|
||||
LocalizationModule,
|
||||
ThemeSharedModule,
|
||||
NgxDatatableModule,
|
||||
ExtensibleModule,
|
||||
PermissionManagementModule,
|
||||
CoreModule,
|
||||
NgbNavModule,
|
||||
PaginatorModule,
|
||||
TagModule,SplitButtonModule
|
||||
],
|
||||
templateUrl: './custom-users.component.html',
|
||||
providers: [
|
||||
ListService,
|
||||
{
|
||||
provide: EXTENSIONS_IDENTIFIER,
|
||||
useValue: eIdentityComponents.Users,
|
||||
},
|
||||
],
|
||||
styleUrl: './custom-users.component.scss',
|
||||
})
|
||||
export class CustomUsersComponent implements OnInit {
|
||||
protected readonly list = inject(ListService<GetIdentityUsersInput>);
|
||||
protected readonly confirmationService = inject(ConfirmationService);
|
||||
protected readonly service = inject(IdentityUserService);
|
||||
protected readonly toasterService = inject(ToasterService);
|
||||
private readonly fb = inject(UntypedFormBuilder);
|
||||
private readonly injector = inject(Injector);
|
||||
@ViewChild('firstDropdownItem') firstDropdownItem: ElementRef;
|
||||
|
||||
data: PagedResultDto<IdentityUserDto> = { items: [], totalCount: 0 };
|
||||
|
||||
@ViewChild('modalContent', { static: false })
|
||||
modalContent!: TemplateRef<any>;
|
||||
|
||||
form!: UntypedFormGroup;
|
||||
password:string;
|
||||
selected?: IdentityUserDto;
|
||||
|
||||
selectedUserRoles?: IdentityRoleDto[];
|
||||
|
||||
// roles?: IdentityRoleDto[];
|
||||
roles: (IdentityRoleDto & { selected: boolean })[] = []; // Use intersection type to add 'selected'
|
||||
|
||||
visiblePermissions = false;
|
||||
|
||||
providerKey?: string;
|
||||
|
||||
isModalVisible?: boolean;
|
||||
|
||||
modalBusy = false;
|
||||
|
||||
permissionManagementKey = ePermissionManagementComponents.PermissionManagement;
|
||||
|
||||
entityDisplayName: string;
|
||||
|
||||
inputKey = eFormComponets.FormCheckboxComponent;
|
||||
|
||||
trackByFn: TrackByFunction<AbstractControl> = (index, item) => Object.keys(item)[0] || index;
|
||||
isDropdownOpen = false;
|
||||
|
||||
toggleDropdown() {
|
||||
this.isDropdownOpen = !this.isDropdownOpen;
|
||||
|
||||
// After the dropdown is shown, focus the first item in the dropdown
|
||||
setTimeout(() => {
|
||||
if (this.firstDropdownItem) {
|
||||
this.firstDropdownItem.nativeElement.focus();
|
||||
}
|
||||
}, 100); // Delay to ensure dropdown is rendered
|
||||
}
|
||||
|
||||
closeDropdown() {
|
||||
this.isDropdownOpen = false;
|
||||
}
|
||||
actionItems = [
|
||||
{ label: 'Edit', icon: 'pi pi-pencil', command: () => this.edit("") },
|
||||
{ label: 'Delete', icon: 'pi pi-trash', command: () => this.delete("","") },
|
||||
// { label: 'Permissions', icon: 'pi pi-shield', command: () => this.openPermissionsModal("") },
|
||||
];
|
||||
|
||||
|
||||
|
||||
onVisiblePermissionChange = (event: boolean) => {
|
||||
debugger
|
||||
this.visiblePermissions = event;
|
||||
};
|
||||
|
||||
get roleGroups(): UntypedFormGroup[] {
|
||||
return ((this.form.get('roleNames') as UntypedFormArray)?.controls as UntypedFormGroup[]) || [];
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.hookToQuery();
|
||||
}
|
||||
formValid() {
|
||||
return true;
|
||||
}
|
||||
// buildForm() {
|
||||
// debugger
|
||||
// const data = new FormPropData(this.injector, this.selected);
|
||||
// this.form = generateFormFromProps(data);
|
||||
|
||||
// this.service.getAssignableRoles().subscribe(({ items }) => {
|
||||
// this.roles = items;
|
||||
// if (this.roles) {
|
||||
// this.form.addControl(
|
||||
// 'roleNames',
|
||||
// this.fb.array(
|
||||
// this.roles.map(role =>
|
||||
// this.fb.group({
|
||||
// [role.name as string]: [
|
||||
// this.selected?.id
|
||||
// ? !!this.selectedUserRoles?.find(userRole => userRole.id === role.id)
|
||||
// : role.isDefault,
|
||||
// ],
|
||||
// }),
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
// openModal() {
|
||||
// this.buildForm();
|
||||
// this.isModalVisible = true;
|
||||
// }
|
||||
|
||||
// add() {
|
||||
// debugger
|
||||
// this.selected = {} as IdentityUserDto;
|
||||
// this.selectedUserRoles = [] as IdentityRoleDto[];
|
||||
// this.openModal();
|
||||
// }
|
||||
|
||||
// edit(id: string) {
|
||||
// debugger
|
||||
// this.service
|
||||
// .get(id)
|
||||
// .pipe(
|
||||
// tap(user => (this.selected = user)),
|
||||
// switchMap(() => this.service.getRoles(id)),
|
||||
// )
|
||||
// .subscribe(userRole => {
|
||||
// debugger
|
||||
|
||||
// this.selectedUserRoles = userRole.items || [];
|
||||
// this.openModal();
|
||||
// });
|
||||
// }
|
||||
|
||||
// save() {
|
||||
// if (!this.form.valid || this.modalBusy) return;
|
||||
// this.modalBusy = true;
|
||||
|
||||
// const { roleNames = [] } = this.form.value;
|
||||
// const mappedRoleNames =
|
||||
// roleNames
|
||||
// .filter((role: { [key: string]: any }) => !!role[Object.keys(role)[0]])
|
||||
// .map((role: { [key: string]: any }) => Object.keys(role)[0]) || [];
|
||||
|
||||
// const { id } = this.selected || {};
|
||||
|
||||
// (id
|
||||
// ? this.service.update(id, {
|
||||
// ...this.selected,
|
||||
// ...this.form.value,
|
||||
// roleNames: mappedRoleNames,
|
||||
// })
|
||||
// : this.service.create({ ...this.form.value, roleNames: mappedRoleNames })
|
||||
// )
|
||||
// .pipe(finalize(() => (this.modalBusy = false)))
|
||||
// .subscribe(() => {
|
||||
// this.isModalVisible = false;
|
||||
// this.toasterService.success('AbpUi::SavedSuccessfully');
|
||||
// this.list.get();
|
||||
// });
|
||||
// }
|
||||
buildForm() {
|
||||
this.service.getAssignableRoles().subscribe(({ items }) => {
|
||||
this.roles = items.map(role => ({
|
||||
...role,
|
||||
selected: this.selectedUserRoles.some(userRole => userRole.id === role.id),
|
||||
}));
|
||||
|
||||
// Initialize the selected roles based on existing data for selected user
|
||||
if (this.selected?.id) {
|
||||
this.roles.forEach(role => {
|
||||
role.selected = this.selectedUserRoles.some(userRole => userRole.id === role.id);
|
||||
});
|
||||
} else {
|
||||
// Default values when creating a new user
|
||||
this.roles.forEach(role => {
|
||||
role.selected = role.isDefault;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
openModal() {
|
||||
this.loadRoles(); // Load roles when modal opens
|
||||
this.isModalVisible = true;
|
||||
}
|
||||
loadRoles() {
|
||||
this.service.getAssignableRoles().subscribe(({ items }) => {
|
||||
this.roles = items.map(role => ({
|
||||
...role, // spread IdentityRoleDto properties
|
||||
selected: false, // Initially no role is selected
|
||||
}));
|
||||
});
|
||||
}
|
||||
add() {
|
||||
this.selected = {} as IdentityUserDto;
|
||||
this.selectedUserRoles = [] as IdentityRoleDto[];
|
||||
this.password = ''; // Store password separately
|
||||
|
||||
this.openModal();
|
||||
}
|
||||
|
||||
edit(id: string) {
|
||||
this.service
|
||||
.get(id)
|
||||
.pipe(finalize(() => this.buildForm()))
|
||||
.subscribe(user => {
|
||||
this.selected = user;
|
||||
this.service.getRoles(id).subscribe(userRoles => {
|
||||
this.selectedUserRoles = userRoles.items || [];
|
||||
});
|
||||
});
|
||||
this.openModal();
|
||||
}
|
||||
|
||||
// Save user data (either create or update)
|
||||
save(form: NgForm) {
|
||||
debugger;
|
||||
if (this.modalBusy || form.invalid) return;
|
||||
|
||||
this.modalBusy = true;
|
||||
|
||||
// Prepare roleNames array
|
||||
// Prepare roleNames array
|
||||
const selectedRoleNames = this.roles
|
||||
.filter(role => role.selected) // Only include selected roles
|
||||
.map(role => role.name); // Extract role names
|
||||
|
||||
// Create user payload
|
||||
|
||||
const userPayload: any = {
|
||||
userName: this.selected.userName,
|
||||
name: this.selected.name,
|
||||
surname: this.selected.surname,
|
||||
email: this.selected.email,
|
||||
phoneNumber: this.selected.phoneNumber,
|
||||
isActive: this.selected.isActive,
|
||||
lockoutEnabled: this.selected.lockoutEnabled,
|
||||
roleNames: selectedRoleNames, // Include selected roles
|
||||
|
||||
};
|
||||
|
||||
// Only include password if creating a new user
|
||||
if (!this.selected.id && this.password) {
|
||||
userPayload.password = this.password;
|
||||
}
|
||||
// Handle create or update
|
||||
const saveObservable = this.selected.id
|
||||
? this.service.update(this.selected.id, userPayload) // Update if id exists
|
||||
: this.service.create(userPayload); // Create if no id
|
||||
|
||||
saveObservable.pipe(finalize(() => (this.modalBusy = false))).subscribe(() => {
|
||||
this.isModalVisible = false;
|
||||
this.toasterService.success('AbpUi::SavedSuccessfully');
|
||||
this.list.get(); // Reload the list if needed
|
||||
});
|
||||
}
|
||||
|
||||
private getRoleNames() {
|
||||
return this.roles.filter(role => role.selected).map(role => role.name);
|
||||
}
|
||||
|
||||
delete(id: string, userName: string) {
|
||||
this.confirmationService
|
||||
.warn('AbpIdentity::UserDeletionConfirmationMessage', 'AbpIdentity::AreYouSure', {
|
||||
messageLocalizationParams: [userName],
|
||||
})
|
||||
.subscribe((status: Confirmation.Status) => {
|
||||
if (status === Confirmation.Status.confirm) {
|
||||
this.service.delete(id).subscribe(() => {
|
||||
this.toasterService.success('AbpUi::DeletedSuccessfully');
|
||||
this.list.get();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
sort(data: any) {
|
||||
const { prop, dir } = data.sorts[0];
|
||||
this.list.sortKey = prop;
|
||||
this.list.sortOrder = dir;
|
||||
}
|
||||
|
||||
// private hookToQuery() {
|
||||
// this.list.hookToQuery(query => this.service.getList(query)).subscribe(res => (this.data = res));
|
||||
// }
|
||||
private hookToQuery() {
|
||||
this.list
|
||||
.hookToQuery(query => {
|
||||
console.log('Query:', query); // Log the query
|
||||
return this.service.getList(query);
|
||||
})
|
||||
.subscribe(res => {
|
||||
debugger;
|
||||
this.data = res;
|
||||
});
|
||||
}
|
||||
|
||||
openPermissionsModal(providerKey: string, entityDisplayName?: string) {
|
||||
debugger;
|
||||
this.providerKey = providerKey;
|
||||
this.entityDisplayName = entityDisplayName;
|
||||
setTimeout(() => {
|
||||
this.visiblePermissions = true;
|
||||
}, 0);
|
||||
}
|
||||
}
|
@ -0,0 +1,212 @@
|
||||
<div>
|
||||
<p-table #dt2 dataKey="id" [value]="patients" [paginator]="true" [rows]="10" [totalRecords]="totalRecords"
|
||||
[lazy]="true" (onLazyLoad)="loadPatient($event)" [rowsPerPageOptions]="[10, 20, 50]"
|
||||
[responsiveLayout]="'scroll'" [globalFilterFields]="['id', 'name', 'status']"
|
||||
[filters]="{ global: { value: '', matchMode: 'contains' } }" class="table table-striped">
|
||||
|
||||
<ng-template pTemplate="caption">
|
||||
<div class="flex">
|
||||
<h2 class="mr-auto">Patient List</h2>
|
||||
<div>
|
||||
<button *ngIf="createpermission" pButton class="p-button-rounded p-button-success ml-2"
|
||||
(click)="openNewPatientDialog()">
|
||||
<i class="pi pi-plus-circle"></i>
|
||||
</button>
|
||||
<button pButton class="p-button-rounded p-button-warning ml-2" (click)="exportPatient()">
|
||||
<i class="pi pi-download"></i>
|
||||
</button>
|
||||
<p-iconField iconPosition="right" class="ml-2">
|
||||
<p-inputIcon>
|
||||
<i class="pi pi-search"></i>
|
||||
</p-inputIcon>
|
||||
<input pInputText type="text" (input)="dt2.filterGlobal($event.target.value, 'contains')"
|
||||
[(ngModel)]="globalFilter" placeholder="Search keyword" />
|
||||
</p-iconField>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<ng-template pTemplate="header">
|
||||
<tr>
|
||||
<th class="hidden" pSortableColumn="id">Patient ID <p-sortIcon field="id" /></th>
|
||||
<th pSortableColumn="name">Full Name <p-sortIcon field="name" /></th>
|
||||
<th pSortableColumn="gender">Gender <p-sortIcon field="gender" /></th>
|
||||
<th pSortableColumn="admissionDate">Date of Admission <p-sortIcon field="admissionDate" /></th>
|
||||
<th pSortableColumn="bloodGroup">Blood Group <p-sortIcon field="bloodGroup" /></th>
|
||||
<th>Mobile</th>
|
||||
<th>Email</th>
|
||||
<th pSortableColumn="status">Status <p-sortIcon field="status" /></th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</ng-template>
|
||||
|
||||
<ng-template pTemplate="body" let-patient>
|
||||
<tr>
|
||||
<td class="hidden">{{ patient.id }}</td>
|
||||
<td>{{ patient.name }}</td>
|
||||
<td>
|
||||
<span class="badge" [ngClass]="patient.gender === 1 ? 'male' : 'female'">
|
||||
{{ gender[patient.gender] }}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ patient.admissionDate | date }}</td>
|
||||
<td>{{ patient.bloodGroup }}</td>
|
||||
<td>{{ patient.mobile }}</td>
|
||||
<td>{{ patient.email }}</td>
|
||||
<td>{{ status[patient.status] }}</td>
|
||||
<td class="d-flex">
|
||||
<button *ngIf="createpermission" pButton class="btn btn-success btn-sm"
|
||||
(click)="addnewrecord(patient.id)">
|
||||
<i class="pi pi-plus-circle"></i>
|
||||
</button>
|
||||
<button *ngIf="editpermission" class="btn btn-warning btn-sm ml-1" (click)="editPatient(patient)"><i
|
||||
class="pi pi-pencil"></i></button>
|
||||
<button *ngIf="deletepermission" class="btn btn-danger btn-sm ml-1"
|
||||
(click)="deletePatient(patient.id)"><i class="pi pi-trash"></i></button>
|
||||
</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
|
||||
<ng-template pTemplate="emptymessage">
|
||||
<tr>
|
||||
<td colspan="10">No Patients found.</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
</p-table>
|
||||
<span>Total Records: {{totalRecords}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<p-dialog *ngIf="patientDialog" header="{{patientDialogTitle}}" [(visible)]="patientDialog" [modal]="true"
|
||||
[closable]="true" [style]="{width: '85%', height: '100%'}">
|
||||
<form #patientrecord="ngForm" (ngSubmit)="savePatient(patientrecord)">
|
||||
<div class="p-fluid">
|
||||
<div class="p-grid">
|
||||
<!-- Full Name -->
|
||||
<div class="p-col-6">
|
||||
<div class="field">
|
||||
<label for="name">Full Name</label>
|
||||
<input id="name" name="name" type="text" pInputText [(ngModel)]="selectedPatient.name"
|
||||
placeholder="Enter full patient name" required #name="ngModel" />
|
||||
<small *ngIf="name.invalid && name.touched" class="p-error">Full Name is required</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Mobile -->
|
||||
<div class="p-col-6">
|
||||
<div class="field">
|
||||
<label for="mobile">Mobile</label>
|
||||
<input id="mobile" name="mobile" type="text" pInputText [(ngModel)]="selectedPatient.mobile"
|
||||
placeholder="Enter mobile number" maxlength="10" required pattern="[0-9]{10}"
|
||||
#mobile="ngModel" />
|
||||
<small *ngIf="mobile.invalid && mobile.touched" class="p-error">
|
||||
Mobile is required and must be 10 digits
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Address -->
|
||||
<div class="p-col-6">
|
||||
<div class="field">
|
||||
<label for="address">Address</label>
|
||||
<input id="address" name="address" type="text" pInputText
|
||||
[(ngModel)]="selectedPatient.address" placeholder="Enter address" required
|
||||
#address="ngModel" />
|
||||
<small *ngIf="address.invalid && address.touched" class="p-error">Address is
|
||||
required</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-grid">
|
||||
<!-- Gender -->
|
||||
<div class="p-col-6">
|
||||
<div class="field">
|
||||
<label for="gender">Gender</label>
|
||||
<div>
|
||||
<label class="mx-1">
|
||||
<input id="male" type="radio" name="gender" [(ngModel)]="selectedgender" [value]="1"
|
||||
required />
|
||||
Male
|
||||
</label>
|
||||
<label>
|
||||
<input id="female" type="radio" name="gender" [(ngModel)]="selectedgender"
|
||||
[value]="2" />
|
||||
Female
|
||||
</label>
|
||||
</div>
|
||||
<small *ngIf="!selectedgender" class="p-error">Gender is required</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Admission Date -->
|
||||
<div class="p-col-6">
|
||||
<div class="field">
|
||||
<label for="admissionDate">Admission Date</label>
|
||||
<p-calendar id="admissionDate" name="admissionDate" [(ngModel)]="selectadmissionDate"
|
||||
showIcon styleClass="small-calendar" required #admissionDate="ngModel"></p-calendar>
|
||||
<small *ngIf="admissionDate.invalid && admissionDate.touched" class="p-error">
|
||||
Admission Date is required
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-grid">
|
||||
<!-- Blood Group -->
|
||||
<div class="p-col-6">
|
||||
<div class="field">
|
||||
<label for="bloodGroup">Blood Group</label>
|
||||
<input id="bloodGroup" name="bloodGroup" type="text" pInputText
|
||||
[(ngModel)]="selectedPatient.bloodGroup" placeholder="Enter blood group" required
|
||||
#bloodGroup="ngModel" />
|
||||
<small *ngIf="bloodGroup.invalid && bloodGroup.touched" class="p-error">Blood Group is
|
||||
required</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Email -->
|
||||
<div class="p-col-6">
|
||||
<div class="field">
|
||||
<label for="email">Email</label>
|
||||
<input id="email" name="email" type="email" pInputText [(ngModel)]="selectedPatient.email"
|
||||
placeholder="Enter email address" required email #email="ngModel" />
|
||||
<small *ngIf="email.invalid && email.touched" class="p-error">Enter a valid email
|
||||
address</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-grid">
|
||||
<!-- Age -->
|
||||
<div class="p-col-6">
|
||||
<div class="field">
|
||||
<label for="age">Age</label>
|
||||
<input id="age" name="age" type="number" pInputText [(ngModel)]="selectedPatient.age"
|
||||
placeholder="Enter age" required min="1" max="120" #age="ngModel" />
|
||||
<small *ngIf="age.invalid && age.touched" class="p-error">
|
||||
Age is required and must be between 1 and 90
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Status -->
|
||||
<div class="p-col-6">
|
||||
<div class="field">
|
||||
<label for="status">Status</label>
|
||||
<p-dropdown name="status" id="status" [options]="statuslist" [(ngModel)]="selectedstatus"
|
||||
optionLabel="label" optionValue="value" placeholder="Select status"
|
||||
required></p-dropdown>
|
||||
<small *ngIf="selectedstatus === 0" class="p-error">Status is required</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button type="submit" pButton class="btn btn-primary"
|
||||
[disabled]="(patientrecord.invalid || selectedstatus === 0 || !selectedgender)">Save</button>
|
||||
<button pButton class="btn btn-secondary ml-1" (click)="closeDialog()">Close</button>
|
||||
</div>
|
||||
</form>
|
||||
</p-dialog>
|
||||
</div>
|
@ -0,0 +1,46 @@
|
||||
/* Adjusting the calendar popup */
|
||||
.small-calendar .p-datepicker {
|
||||
width: 200px !important; /* Adjust the width as per your needs */
|
||||
font-size: 12px !important; /* Adjust the font size */
|
||||
}
|
||||
|
||||
.small-calendar .p-datepicker-header {
|
||||
padding: 2px !important; /* Adjust the header padding */
|
||||
}
|
||||
|
||||
.small-calendar .p-datepicker-calendar th {
|
||||
font-size: 10px !important; /* Smaller font size for the header */
|
||||
}
|
||||
|
||||
.small-calendar .p-datepicker-calendar td {
|
||||
font-size: 10px !important; /* Smaller font size for the days */
|
||||
}
|
||||
|
||||
.table-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.badge {
|
||||
display: inline-block;
|
||||
padding: 0.2rem 0.6rem;
|
||||
border-radius: 0.5rem;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.male {
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
.female {
|
||||
background-color: purple;
|
||||
}
|
||||
|
||||
.pdf-icon {
|
||||
color: red;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
226
angular/src/app/patients/all-patients/all-patients.component.ts
Normal file
226
angular/src/app/patients/all-patients/all-patients.component.ts
Normal file
@ -0,0 +1,226 @@
|
||||
import { PermissionService } from '@abp/ng.core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { NgForm } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
import { PagingSortPatientResultDto } from '@proxy/dto';
|
||||
import { Gender, Status } from '@proxy/global-enum';
|
||||
import { PatientService } from '@proxy/patients';
|
||||
import { PatientDto, CreateUpdatePatientDto } from '@proxy/patients/dto';
|
||||
import { MessageService } from 'primeng/api';
|
||||
|
||||
@Component({
|
||||
selector: 'app-all-patients',
|
||||
templateUrl: './all-patients.component.html',
|
||||
styleUrl: './all-patients.component.scss',
|
||||
providers: [PatientService, MessageService, PermissionService],
|
||||
})
|
||||
export class AllPatientsComponent implements OnInit {
|
||||
globalFilter: string = '';
|
||||
patients: PatientDto[];
|
||||
totalRecords: number = 0;
|
||||
loading: boolean = false;
|
||||
patientDialog: boolean = false;
|
||||
selectedPatient: CreateUpdatePatientDto;
|
||||
isEditMode: boolean = false;
|
||||
patientDialogTitle: string = '';
|
||||
params: PagingSortPatientResultDto;
|
||||
status: any;
|
||||
gender: any;
|
||||
statuslist: any;
|
||||
selectedstatus: any = 0;
|
||||
selectedgender: any = 0;
|
||||
selectadmissionDate: Date = new Date();
|
||||
selectdischargeDate: Date = new Date();
|
||||
uploadfile: {
|
||||
file: File[];
|
||||
name: string;
|
||||
}[] = [];
|
||||
createpermission: boolean;
|
||||
editpermission: boolean;
|
||||
deletepermission: boolean;
|
||||
|
||||
constructor(
|
||||
private patientService: PatientService,
|
||||
private http: HttpClient,
|
||||
private messageService: MessageService,
|
||||
private permissionChecker: PermissionService,
|
||||
private router: Router
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.createpermission = this.permissionChecker.getGrantedPolicy(
|
||||
'HospitalManagementSystem.Patient.Create'
|
||||
);
|
||||
this.editpermission = this.permissionChecker.getGrantedPolicy(
|
||||
'HospitalManagementSystem.Patient.Edit'
|
||||
);
|
||||
this.deletepermission = this.permissionChecker.getGrantedPolicy(
|
||||
'HospitalManagementSystem.Patient.Delete'
|
||||
);
|
||||
this.status = Status;
|
||||
this.gender = Gender;
|
||||
this.patientService.getStatusDropdown().subscribe(result => {
|
||||
this.statuslist = result;
|
||||
});
|
||||
|
||||
this.resetselectpatient();
|
||||
this.loadPatient({
|
||||
first: 0,
|
||||
rows: 10,
|
||||
sortField: 'id',
|
||||
sortOrder: 1,
|
||||
globalFilter: null,
|
||||
});
|
||||
}
|
||||
resetselectpatient() {
|
||||
this.selectedPatient = {
|
||||
name: '',
|
||||
gender: Gender.Male,
|
||||
mobile: '',
|
||||
email: '',
|
||||
age: 0,
|
||||
treatment: '',
|
||||
doctorAssigned: '',
|
||||
address: '',
|
||||
bloodGroup: '',
|
||||
admissionDate: '',
|
||||
dischargeDate: '',
|
||||
status: Status.InTreatment,
|
||||
};
|
||||
}
|
||||
|
||||
loadPatient(event: any) {
|
||||
this.loading = true;
|
||||
let order = event.sortOrder == 1 ? ' asc' : ' desc';
|
||||
event.sortField = event.sortField == undefined ? 'id' : event.sortField;
|
||||
this.params = {
|
||||
skipCount: event.first,
|
||||
maxResultCount: event.rows,
|
||||
sorting: event.sortField + order,
|
||||
search: event.globalFilter == null ? '' : event.globalFilter,
|
||||
};
|
||||
|
||||
this.patientService.getPatientList(this.params).subscribe(data => {
|
||||
this.patients = data.items;
|
||||
this.totalRecords = data.totalCount;
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
exportPatient() {
|
||||
this.patientService.getExportPatientData().subscribe(result => {
|
||||
const binary = atob(result.fileContent);
|
||||
const len = binary.length;
|
||||
const bytes = new Uint8Array(len);
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
bytes[i] = binary.charCodeAt(i);
|
||||
}
|
||||
|
||||
const blob = new Blob([bytes], { type: 'application/xlsx' });
|
||||
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = result.fileName;
|
||||
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
|
||||
document.body.removeChild(link);
|
||||
window.URL.revokeObjectURL(url);
|
||||
});
|
||||
}
|
||||
|
||||
openNewPatientDialog() {
|
||||
this.patientDialogTitle = 'New Patient';
|
||||
this.resetselectpatient();
|
||||
this.selectedgender = 0;
|
||||
this.selectedstatus = 0;
|
||||
this.patientDialog = true;
|
||||
this.isEditMode = false;
|
||||
}
|
||||
|
||||
addnewrecord(id: any) {
|
||||
this.router.navigate(['/patients/patient-record', id]);
|
||||
}
|
||||
|
||||
editPatient(Patient: any) {
|
||||
this.patientDialogTitle = 'Edit Patient';
|
||||
this.selectedPatient = { ...Patient };
|
||||
this.selectedgender = this.selectedPatient.gender;
|
||||
this.selectedstatus = this.selectedPatient.status;
|
||||
this.selectadmissionDate = new Date(this.selectedPatient.admissionDate);
|
||||
this.selectdischargeDate = new Date(this.selectedPatient.dischargeDate);
|
||||
this.patientDialog = true;
|
||||
this.isEditMode = true;
|
||||
}
|
||||
|
||||
deletePatient(id: any) {
|
||||
this.patientService.deletePatient(id).subscribe(() => {
|
||||
this.messageService.add({
|
||||
severity: 'success',
|
||||
summary: 'Success',
|
||||
detail: 'Patient deleted successfully',
|
||||
});
|
||||
this.loadPatient(this.params);
|
||||
});
|
||||
}
|
||||
|
||||
savePatient(form: NgForm) {
|
||||
debugger;
|
||||
console.log(form.controls);
|
||||
if (form.invalid) {
|
||||
Object.values(form.controls).forEach(control => control.markAsTouched());
|
||||
return;
|
||||
}
|
||||
this.selectedPatient.gender = this.selectedgender;
|
||||
this.selectedPatient.status = this.selectedstatus;
|
||||
this.selectedPatient.admissionDate = this.selectadmissionDate.toDateString();
|
||||
this.selectedPatient.dischargeDate = this.selectdischargeDate.toDateString();
|
||||
|
||||
console.log(this.selectedPatient);
|
||||
|
||||
if (this.isEditMode) {
|
||||
this.patientService
|
||||
.updatePatient(this.selectedPatient.id, this.selectedPatient)
|
||||
.subscribe(() => {
|
||||
this.messageService.add({
|
||||
severity: 'success',
|
||||
summary: 'Success',
|
||||
detail: 'Patient updated successfully',
|
||||
});
|
||||
this.patientDialog = false;
|
||||
this.loadPatient({
|
||||
first: 0,
|
||||
rows: 10,
|
||||
sortField: 'id',
|
||||
sortOrder: 1,
|
||||
globalFilter: null,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
this.patientService.createPatient(this.selectedPatient).subscribe(() => {
|
||||
this.messageService.add({
|
||||
severity: 'success',
|
||||
summary: 'Success',
|
||||
detail: 'Patient created successfully',
|
||||
});
|
||||
this.patientDialog = false;
|
||||
this.loadPatient({
|
||||
first: 0,
|
||||
rows: 10,
|
||||
sortField: 'id',
|
||||
sortOrder: 1,
|
||||
globalFilter: null,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
closeDialog() {
|
||||
this.patientDialog = false;
|
||||
}
|
||||
}
|
@ -0,0 +1,266 @@
|
||||
<div class="patient-container">
|
||||
<div class="patient-card">
|
||||
<!-- Patient Image -->
|
||||
<div class="patient-image">
|
||||
<img [src]="patientImageUrl || 'assets/default-profile.png'" alt="Patient Image">
|
||||
</div>
|
||||
|
||||
<!-- Patient Information -->
|
||||
<div class="patient-info">
|
||||
<h2 class="patient-name">{{ patientdto?.name }}</h2>
|
||||
<div class="patient-details">
|
||||
<div class="info-item">
|
||||
<strong>Age:</strong> {{ patientdto?.age }}
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<strong>Gender:</strong> {{ gender[patientdto?.gender] }}
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<strong>Mobile:</strong> {{ patientdto?.mobile }}
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<strong>Email:</strong> {{ patientdto?.email }}
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<strong>Blood Group:</strong> {{ patientdto?.bloodGroup }}
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<strong>Doctor:</strong> {{ patientdto?.doctorAssigned || 'N/A' }}
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<strong>Admission:</strong> {{ patientdto?.admissionDate | date }}
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<strong>Status:</strong>
|
||||
<span class="status" [ngClass]="{'active': patientdto?.status === 'Active', 'inactive': patientdto?.status === 'Inactive'}">
|
||||
{{ status[patientdto?.status] }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div>
|
||||
<p-table #dt2 dataKey="id" [value]="patientrecords" [paginator]="true" [rows]="10" [totalRecords]="totalRecords"
|
||||
[lazy]="true" (onLazyLoad)="loadPatient($event,userid)" [rowsPerPageOptions]="[10, 20, 50]"
|
||||
[responsiveLayout]="'scroll'" [globalFilterFields]="['id', 'name', 'diagnosis']"
|
||||
[filters]="{ global: { value: '', matchMode: 'contains' } }" class="table table-striped">
|
||||
|
||||
<ng-template pTemplate="caption">
|
||||
<div class="flex">
|
||||
<h2 class="mr-auto">{{'::PatientHeader' | abpLocalization}}</h2>
|
||||
<div>
|
||||
<button *ngIf="createpermission" pButton class="p-button-rounded p-button-success ml-2"
|
||||
(click)="openNewPatientDialog()">
|
||||
<i class="pi pi-plus-circle"></i>
|
||||
</button>
|
||||
<button pButton class="p-button-rounded p-button-warning ml-2" (click)="exportPatient()">
|
||||
<i class="pi pi-download"></i>
|
||||
</button>
|
||||
<p-iconField iconPosition="right" class="ml-2">
|
||||
<p-inputIcon>
|
||||
<i class="pi pi-search"></i>
|
||||
</p-inputIcon>
|
||||
<input pInputText type="text" (input)="dt2.filterGlobal($event.target.value, 'contains')"
|
||||
[(ngModel)]="globalFilter" placeholder="Search keyword" />
|
||||
</p-iconField>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<ng-template pTemplate="header">
|
||||
<tr>
|
||||
<th class="hidden" pSortableColumn="id">Patient ID <p-sortIcon field="id" /></th>
|
||||
<th pSortableColumn="fullName">Full Name <p-sortIcon field="fullName" /></th>
|
||||
<th pSortableColumn="gender">Gender <p-sortIcon field="fullName" /></th>
|
||||
<th pSortableColumn="dateOfAdmission">Date of Admission <p-sortIcon field="dateOfAdmission" /></th>
|
||||
<th pSortableColumn="diagnosis">Diagnosis <p-sortIcon field="diagnosis" /></th>
|
||||
<th>Lab Reports</th>
|
||||
<th>Medications</th>
|
||||
<th pSortableColumn="nextFollowUp">Next Follow-Up <p-sortIcon field="nextFollowUp" /></th>
|
||||
<th pSortableColumn="status">Status <p-sortIcon field="status" /></th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</ng-template>
|
||||
|
||||
<ng-template pTemplate="body" let-patientrecord>
|
||||
<tr>
|
||||
<td class="hidden">{{ patientrecord.id }}</td>
|
||||
<td>{{ patientrecord.patients.name }}</td>
|
||||
<td>
|
||||
<span class="badge" [ngClass]="patientrecord.patients.gender === 1 ? 'male' : 'female'">
|
||||
{{ gender[patientrecord.patients.gender] }}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ patientrecord.dateOfAdmission | date }}</td>
|
||||
<td>{{ patientrecord.diagnosis }}</td>
|
||||
<td><i class="pi pi-file-pdf pdf-icon"></i></td>
|
||||
<td><i class="pi pi-file-pdf pdf-icon"></i></td>
|
||||
<td>{{ patientrecord.nextFollowUp | date }}</td>
|
||||
<td>{{ status[patientrecord.patients.status] }}</td>
|
||||
<td class="d-flex">
|
||||
<button *ngIf="editpermission" class="btn btn-warning btn-sm" (click)="editPatient(patientrecord)"><i
|
||||
class="pi pi-pencil"></i></button>
|
||||
<button *ngIf="deletepermission" class="btn btn-danger btn-sm ml-1" (click)="deletePatient(patientrecord.id)"><i
|
||||
class="pi pi-trash"></i></button>
|
||||
</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
<ng-template pTemplate="emptymessage">
|
||||
<tr>
|
||||
<td colspan="11">No Patients found.</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
</p-table>
|
||||
<span>Total Records: {{totalRecords}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<p-dialog *ngIf="patientDialog" header="{{patientDialogTitle}}" [(visible)]="patientDialog" [modal]="true"
|
||||
[closable]="true" [style]="{width: '85%', height: '100%'}">
|
||||
<form #patientrecord="ngForm" (ngSubmit)="savePatient(patientrecord)" novalidate>
|
||||
<div class="p-fluid">
|
||||
<div class="p-grid">
|
||||
<!-- <div class="p-col-6">
|
||||
<div class="field">
|
||||
<label for="fullname">Full Name</label>
|
||||
<input id="fullname" name="fullname" type="text" autocomplete="off" pInputText
|
||||
[(ngModel)]="selectedPatient.fullName" placeholder="Enter full patient name" required
|
||||
#fullname="ngModel" />
|
||||
<small *ngIf="fullname.invalid && fullname.touched" class="p-error">
|
||||
Full Name is required.
|
||||
</small>
|
||||
</div>
|
||||
</div> -->
|
||||
<!-- <div class="p-col-6">
|
||||
<div class="field">
|
||||
<label for="mobile">Mobile</label>
|
||||
<input id="mobile" name="mobile" type="text" autocomplete="off" pInputText
|
||||
[(ngModel)]="selectedPatient.mobile" maxlength="10" pattern="^[0-9]{10}$"
|
||||
placeholder="Enter mobile number" required #mobile="ngModel" />
|
||||
<small *ngIf="mobile.invalid && mobile.touched" class="p-error">
|
||||
Mobile number is required and must be 10 digits.
|
||||
</small>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
<div class="p-grid">
|
||||
<div class="p-col-6">
|
||||
<!-- <div class="field">
|
||||
<label for="gender">Gender</label>
|
||||
<div>
|
||||
<label class="mx-1">
|
||||
<input style="background-color: #fff;" id="male" type="radio" name="gender"
|
||||
[(ngModel)]="selectedgender" [value]="1" required #gender="ngModel" />
|
||||
Male
|
||||
</label>
|
||||
<label>
|
||||
<input style="background-color: #fff;" id="female" type="radio" name="gender"
|
||||
[(ngModel)]="selectedgender" [value]="2" required />
|
||||
Female
|
||||
</label>
|
||||
<small *ngIf="!selectedgender" class="p-error">
|
||||
Please select a gender.
|
||||
</small>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
<div class="p-col-6">
|
||||
<div class="field">
|
||||
<label for="admissionDate">Admission Date</label>
|
||||
<p-calendar id="admissionDate" name="admissionDate" [(ngModel)]="selectdateOfAdmission" showIcon required
|
||||
#admissionDate="ngModel"></p-calendar>
|
||||
<small *ngIf="admissionDate.invalid && admissionDate.touched" class="p-error">
|
||||
Admission Date is required.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-grid">
|
||||
<div class="p-col-6">
|
||||
<div class="field">
|
||||
<label for="labReport">Lab Report</label>
|
||||
<input type="file" id="labReport" name="labReport" accept=".pdf,.doc,.docx"
|
||||
(change)="handleLabReportUpload($event)" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-col-6">
|
||||
<div class="field">
|
||||
<label for="medications">Medications</label>
|
||||
<input type="file" id="medications" name="medications" accept=".pdf,.doc,.docx"
|
||||
(change)="handleMedicationsUpload($event)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-grid">
|
||||
<div class="p-col-6">
|
||||
<div class="field">
|
||||
<label for="medicationHistory">Medication History</label>
|
||||
<input type="file" id="medicationHistory" name="medicationHistory" accept=".pdf,.doc,.docx"
|
||||
(change)="handleMedicationHistoryUpload($event)" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-col-6">
|
||||
<div class="field">
|
||||
<label for="nextFollowUp">Next FollowUp Date</label>
|
||||
<p-calendar id="nextFollowUp" name="nextFollowUp" [(ngModel)]="selectnextFollowUp" showIcon required
|
||||
#nextFollowUp="ngModel"></p-calendar>
|
||||
<small *ngIf="nextFollowUp.invalid && nextFollowUp.touched" class="p-error">
|
||||
Next Follow-Up Date is required.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-grid">
|
||||
<div class="p-col-12">
|
||||
<div class="field">
|
||||
<div>
|
||||
<label for="diagnosis">Diagnosis</label>
|
||||
</div>
|
||||
<textarea style="width: 100%; background-color: #fff; color: black;" id="diagnosis" name="diagnosis"
|
||||
pInputTextarea rows="5" cols="30" [(ngModel)]="selectedPatient.diagnosis" required
|
||||
#diagnosis="ngModel"></textarea>
|
||||
<small *ngIf="diagnosis.invalid && diagnosis.touched" class="p-error">
|
||||
Diagnosis is required.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-grid">
|
||||
<div class="p-col-6">
|
||||
<div class="field">
|
||||
<label for="insuranceProvider">Insurance Provider</label>
|
||||
<input id="insuranceProvider" name="insuranceProvider" type="text" autocomplete="off" pInputText
|
||||
[(ngModel)]="selectedPatient.insuranceProvider" required placeholder="Enter insurance provider" #insurance="ngModel" />
|
||||
<small *ngIf="insurance.invalid && insurance.touched" class="p-error">
|
||||
Insurance is required.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-col-6">
|
||||
<!-- <div class="field">
|
||||
<label for="status">Status</label>
|
||||
<p-dropdown name="status" id="status" [options]="statuslist" [(ngModel)]="selectedstatus"
|
||||
optionLabel="label" optionValue="value" placeholder="Select status" required
|
||||
#status="ngModel"></p-dropdown>
|
||||
<small *ngIf="selectedstatus === 0" class="p-error">
|
||||
Status is required.
|
||||
</small>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button type="submit" pButton class="btn btn-primary"
|
||||
[disabled]="patientrecord.invalid">Save</button>
|
||||
<button pButton class="btn btn-secondary ml-1" (click)="closeDialog()">Close</button>
|
||||
</div>
|
||||
</form>
|
||||
</p-dialog>
|
||||
</div>
|
@ -0,0 +1,96 @@
|
||||
.table-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.badge {
|
||||
display: inline-block;
|
||||
padding: 0.2rem 0.6rem;
|
||||
border-radius: 0.5rem;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.male {
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
.female {
|
||||
background-color: purple;
|
||||
}
|
||||
|
||||
.pdf-icon {
|
||||
color: red;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
|
||||
.patient-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.patient-card {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
background: #ffffff;
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.1);
|
||||
border-left: 5px solid #007bff;
|
||||
}
|
||||
|
||||
.patient-image img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
border: 3px solid #007bff;
|
||||
}
|
||||
|
||||
.patient-info {
|
||||
flex: 1;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.patient-name {
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.patient-details {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(150px, 1fr));
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
font-size: 14px;
|
||||
background: #f8f9fa;
|
||||
padding: 6px 12px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.status {
|
||||
font-weight: bold;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.status.active {
|
||||
background: #28a745;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.status.inactive {
|
||||
background: #dc3545;
|
||||
color: white;
|
||||
}
|
||||
|
@ -0,0 +1,254 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { NgForm } from '@angular/forms';
|
||||
import { PagingSortPatientResultDto } from '@proxy/dto';
|
||||
import { Gender, Status } from '@proxy/global-enum';
|
||||
import { PatientService } from '@proxy/patients';
|
||||
import { CreateUpdatePatientRecordDto, PatientDto, PatientRecordDto } from '@proxy/patients/dto';
|
||||
import { MessageService } from 'primeng/api';
|
||||
import { PermissionService } from '@abp/ng.core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-patient-record',
|
||||
templateUrl: './patient-record.component.html',
|
||||
styleUrl: './patient-record.component.scss',
|
||||
providers: [PatientService, MessageService, PermissionService],
|
||||
})
|
||||
export class PatientRecordComponent implements OnInit {
|
||||
globalFilter: string = '';
|
||||
patientrecords: PatientRecordDto[];
|
||||
totalRecords: number = 0;
|
||||
loading: boolean = false;
|
||||
patientDialog: boolean = false;
|
||||
selectedPatient: CreateUpdatePatientRecordDto;
|
||||
patientdto: PatientDto;
|
||||
isEditMode: boolean = false;
|
||||
patientDialogTitle: string = '';
|
||||
params: PagingSortPatientResultDto;
|
||||
status: any;
|
||||
gender: any;
|
||||
statuslist: any;
|
||||
selectdateOfAdmission: Date = new Date();
|
||||
selectnextFollowUp: Date = new Date();
|
||||
uploadfile: {
|
||||
file: File[];
|
||||
name: string;
|
||||
}[] = [];
|
||||
createpermission: boolean;
|
||||
editpermission: boolean;
|
||||
deletepermission: boolean;
|
||||
userid: any;
|
||||
patientImageUrl: string;
|
||||
|
||||
constructor(
|
||||
private patientService: PatientService,
|
||||
private messageService: MessageService,
|
||||
private permissionChecker: PermissionService,
|
||||
private route: ActivatedRoute
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.userid = this.route.snapshot.paramMap.get('id');
|
||||
console.log(this.userid);
|
||||
|
||||
this.createpermission = this.permissionChecker.getGrantedPolicy(
|
||||
'HospitalManagementSystem.Patient.Create'
|
||||
);
|
||||
this.editpermission = this.permissionChecker.getGrantedPolicy(
|
||||
'HospitalManagementSystem.Patient.Edit'
|
||||
);
|
||||
this.deletepermission = this.permissionChecker.getGrantedPolicy(
|
||||
'HospitalManagementSystem.Patient.Delete'
|
||||
);
|
||||
this.status = Status;
|
||||
this.gender = Gender;
|
||||
this.patientService.getStatusDropdown().subscribe(result => {
|
||||
this.statuslist = result;
|
||||
});
|
||||
|
||||
this.resetselectpatient();
|
||||
}
|
||||
|
||||
resetselectpatient() {
|
||||
this.selectedPatient = {
|
||||
patientId: this.userid,
|
||||
dateOfAdmission: '',
|
||||
labReportUrl: '',
|
||||
medicationUrl: '',
|
||||
medicationHistoryUrl: '',
|
||||
nextFollowUp: '',
|
||||
diagnosis: '',
|
||||
treatmentPlan: '',
|
||||
doctorNotes: '',
|
||||
insuranceProvider: '',
|
||||
status: Status.InTreatment,
|
||||
};
|
||||
}
|
||||
|
||||
loadPatient(event: any, id: any) {
|
||||
this.selectedPatient.patientId = this.userid;
|
||||
this.loading = true;
|
||||
let order = event.sortOrder == 1 ? ' asc' : ' desc';
|
||||
event.sortField = event.sortField == undefined ? 'id' : event.sortField;
|
||||
this.params = {
|
||||
skipCount: event.first,
|
||||
maxResultCount: event.rows,
|
||||
sorting: event.sortField + order,
|
||||
search: event.globalFilter == null ? '' : event.globalFilter,
|
||||
};
|
||||
this.patientService.getPatientById(this.userid).subscribe(result => {
|
||||
this.patientdto = result;
|
||||
});
|
||||
this.patientService.getPatientRecordList(this.params, id).subscribe(data => {
|
||||
this.patientrecords = data.items;
|
||||
this.totalRecords = data.totalCount;
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
exportPatient() {
|
||||
this.patientService.getExportPatientRecord().subscribe(result => {
|
||||
const binary = atob(result.fileContent);
|
||||
const len = binary.length;
|
||||
const bytes = new Uint8Array(len);
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
bytes[i] = binary.charCodeAt(i);
|
||||
}
|
||||
|
||||
const blob = new Blob([bytes], { type: 'application/xlsx' });
|
||||
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = result.fileName;
|
||||
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
|
||||
document.body.removeChild(link);
|
||||
window.URL.revokeObjectURL(url);
|
||||
});
|
||||
}
|
||||
|
||||
openNewPatientDialog() {
|
||||
this.patientDialogTitle = 'New Patient Record';
|
||||
this.resetselectpatient();
|
||||
this.patientDialog = true;
|
||||
this.isEditMode = false;
|
||||
}
|
||||
|
||||
editPatient(Patient: any) {
|
||||
this.patientDialogTitle = 'Edit Patient';
|
||||
this.selectedPatient = { ...Patient };
|
||||
this.selectedPatient.patientId = this.userid;
|
||||
this.selectdateOfAdmission = new Date(this.selectedPatient.dateOfAdmission);
|
||||
this.selectnextFollowUp = new Date(this.selectedPatient.nextFollowUp);
|
||||
this.patientDialog = true;
|
||||
this.isEditMode = true;
|
||||
console.log(this.selectedPatient);
|
||||
}
|
||||
|
||||
deletePatient(id: any) {
|
||||
this.patientService.deletePatientRecord(id).subscribe(() => {
|
||||
this.messageService.add({
|
||||
severity: 'success',
|
||||
summary: 'Success',
|
||||
detail: 'Patient deleted successfully',
|
||||
});
|
||||
this.loadPatient(this.params, this.userid);
|
||||
});
|
||||
}
|
||||
|
||||
// handleLabReportUpload(event: any): void {
|
||||
// const input = event.target as HTMLInputElement;
|
||||
// console.log(input);
|
||||
// const files: File[] = event.files; // Files uploaded
|
||||
// this.addToUploadList(files, 'Lab-Report');
|
||||
// }
|
||||
handleLabReportUpload(event: Event): void {
|
||||
const input = event.target as HTMLInputElement;
|
||||
if (input && input.files) {
|
||||
const files: File[] = Array.from(input.files); // Convert FileList to an array of File
|
||||
this.addToUploadList(files, 'Lab-Report');
|
||||
} else {
|
||||
console.error('No files selected');
|
||||
}
|
||||
}
|
||||
|
||||
handleMedicationsUpload(event: any): void {
|
||||
const files: File[] = event.files; // Files uploaded
|
||||
this.addToUploadList(files, 'Medications');
|
||||
}
|
||||
|
||||
handleMedicationHistoryUpload(event: any): void {
|
||||
const files: File[] = event.files; // Files uploaded
|
||||
this.addToUploadList(files, 'Medication-History');
|
||||
}
|
||||
|
||||
private addToUploadList(files: File[], name: string): void {
|
||||
const existingIndex = this.uploadfile.findIndex(item => item.name === name);
|
||||
|
||||
if (existingIndex > -1) {
|
||||
this.uploadfile[existingIndex].file = files;
|
||||
} else {
|
||||
this.uploadfile.push({ file: files, name });
|
||||
}
|
||||
console.log(this.uploadfile);
|
||||
}
|
||||
|
||||
savePatient(form: NgForm) {
|
||||
// console.log(form);
|
||||
this.selectedPatient.patientId = this.userid;
|
||||
this.selectedPatient.status = this.patientdto.status;
|
||||
this.selectedPatient.dateOfAdmission = this.selectdateOfAdmission.toDateString();
|
||||
this.selectedPatient.nextFollowUp = this.selectnextFollowUp.toDateString();
|
||||
|
||||
if (this.isEditMode) {
|
||||
this.patientService
|
||||
.updatePatientRecord(this.selectedPatient.id, this.selectedPatient)
|
||||
.subscribe(() => {
|
||||
this.messageService.add({
|
||||
severity: 'success',
|
||||
summary: 'Success',
|
||||
detail: 'Patient updated successfully',
|
||||
});
|
||||
this.patientDialog = false;
|
||||
this.loadPatient(
|
||||
{
|
||||
first: 0,
|
||||
rows: 10,
|
||||
sortField: 'id',
|
||||
sortOrder: 1,
|
||||
globalFilter: null,
|
||||
},
|
||||
this.userid
|
||||
);
|
||||
});
|
||||
} else {
|
||||
this.patientService.createPatientRecord(this.selectedPatient).subscribe(() => {
|
||||
this.messageService.add({
|
||||
severity: 'success',
|
||||
summary: 'Success',
|
||||
detail: 'Patient created successfully',
|
||||
});
|
||||
this.patientDialog = false;
|
||||
this.loadPatient(
|
||||
{
|
||||
first: 0,
|
||||
rows: 10,
|
||||
sortField: 'id',
|
||||
sortOrder: 1,
|
||||
globalFilter: null,
|
||||
},
|
||||
this.userid
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
closeDialog() {
|
||||
this.patientDialog = false;
|
||||
}
|
||||
}
|
26
angular/src/app/patients/patients-routing.module.ts
Normal file
26
angular/src/app/patients/patients-routing.module.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { AllPatientsComponent } from './all-patients/all-patients.component';
|
||||
import { PatientRecordComponent } from './patient-record/patient-record.component';
|
||||
import { authGuard, permissionGuard } from '@abp/ng.core';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
children: [
|
||||
{
|
||||
path: 'patient-record/:id',
|
||||
component: PatientRecordComponent,
|
||||
// canActivate: [authGuard, permissionGuard],
|
||||
},
|
||||
{ path: 'all-patients', component: AllPatientsComponent },
|
||||
// { path: 'create-new/:id', component: FaqCreateComponent },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class PatientsRoutingModule {}
|
37
angular/src/app/patients/patients.module.ts
Normal file
37
angular/src/app/patients/patients.module.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { PatientsRoutingModule } from './patients-routing.module';
|
||||
import { AllPatientsComponent } from './all-patients/all-patients.component';
|
||||
import { PatientRecordComponent } from './patient-record/patient-record.component';
|
||||
import { TableModule } from 'primeng/table';
|
||||
import { IconFieldModule } from 'primeng/iconfield';
|
||||
import { InputIconModule } from 'primeng/inputicon';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { InputTextModule } from 'primeng/inputtext';
|
||||
import { PaginatorModule } from 'primeng/paginator';
|
||||
import { DialogModule } from 'primeng/dialog';
|
||||
import { DropdownModule } from 'primeng/dropdown';
|
||||
import { FileUploadModule } from 'primeng/fileupload';
|
||||
import { CalendarModule } from 'primeng/calendar';
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [AllPatientsComponent, PatientRecordComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
PatientsRoutingModule,
|
||||
TableModule,
|
||||
InputIconModule,
|
||||
IconFieldModule,
|
||||
FormsModule,
|
||||
InputTextModule,
|
||||
PaginatorModule,
|
||||
DialogModule,
|
||||
DropdownModule,
|
||||
FileUploadModule,
|
||||
CalendarModule,
|
||||
SharedModule
|
||||
],
|
||||
})
|
||||
export class PatientsModule {}
|
1
angular/src/app/proxy/dto/index.ts
Normal file
1
angular/src/app/proxy/dto/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './models';
|
15
angular/src/app/proxy/dto/models.ts
Normal file
15
angular/src/app/proxy/dto/models.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import type { PagedAndSortedResultRequestDto } from '@abp/ng.core';
|
||||
|
||||
export interface DropDownItems {
|
||||
label?: string;
|
||||
value: number;
|
||||
}
|
||||
|
||||
export interface FileDownloadDto {
|
||||
fileName?: string;
|
||||
fileContent?: string;
|
||||
}
|
||||
|
||||
export interface PagingSortPatientResultDto extends PagedAndSortedResultRequestDto {
|
||||
search?: string;
|
||||
}
|
10387
angular/src/app/proxy/generate-proxy.json
Normal file
10387
angular/src/app/proxy/generate-proxy.json
Normal file
File diff suppressed because it is too large
Load Diff
8
angular/src/app/proxy/global-enum/gender.enum.ts
Normal file
8
angular/src/app/proxy/global-enum/gender.enum.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { mapEnumToOptions } from '@abp/ng.core';
|
||||
|
||||
export enum Gender {
|
||||
Male = 1,
|
||||
Female = 2,
|
||||
}
|
||||
|
||||
export const genderOptions = mapEnumToOptions(Gender);
|
2
angular/src/app/proxy/global-enum/index.ts
Normal file
2
angular/src/app/proxy/global-enum/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './gender.enum';
|
||||
export * from './status.enum';
|
9
angular/src/app/proxy/global-enum/status.enum.ts
Normal file
9
angular/src/app/proxy/global-enum/status.enum.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { mapEnumToOptions } from '@abp/ng.core';
|
||||
|
||||
export enum Status {
|
||||
Recovered = 1,
|
||||
Observation = 2,
|
||||
InTreatment = 3,
|
||||
}
|
||||
|
||||
export const statusOptions = mapEnumToOptions(Status);
|
4
angular/src/app/proxy/index.ts
Normal file
4
angular/src/app/proxy/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
import * as Dto from './dto';
|
||||
import * as GlobalEnum from './global-enum';
|
||||
import * as Patients from './patients';
|
||||
export { Dto, GlobalEnum, Patients };
|
1
angular/src/app/proxy/patients/dto/index.ts
Normal file
1
angular/src/app/proxy/patients/dto/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './models';
|
65
angular/src/app/proxy/patients/dto/models.ts
Normal file
65
angular/src/app/proxy/patients/dto/models.ts
Normal file
@ -0,0 +1,65 @@
|
||||
import type { Gender } from '../../global-enum/gender.enum';
|
||||
import type { Status } from '../../global-enum/status.enum';
|
||||
|
||||
export interface CreateUpdatePatientDto {
|
||||
id?: string;
|
||||
name?: string;
|
||||
gender: Gender;
|
||||
mobile?: string;
|
||||
email?: string;
|
||||
age: number;
|
||||
treatment?: string;
|
||||
doctorAssigned?: string;
|
||||
address?: string;
|
||||
bloodGroup?: string;
|
||||
admissionDate?: string;
|
||||
dischargeDate?: string;
|
||||
status: Status;
|
||||
}
|
||||
|
||||
export interface CreateUpdatePatientRecordDto {
|
||||
id?: string;
|
||||
patientId?: string;
|
||||
dateOfAdmission?: string;
|
||||
labReportUrl?: string;
|
||||
medicationUrl?: string;
|
||||
medicationHistoryUrl?: string;
|
||||
nextFollowUp?: string;
|
||||
diagnosis?: string;
|
||||
treatmentPlan?: string;
|
||||
doctorNotes?: string;
|
||||
insuranceProvider?: string;
|
||||
status: Status;
|
||||
}
|
||||
|
||||
export interface PatientDto {
|
||||
id?: string;
|
||||
name?: string;
|
||||
gender: Gender;
|
||||
mobile?: string;
|
||||
email?: string;
|
||||
age: number;
|
||||
treatment?: string;
|
||||
doctorAssigned?: string;
|
||||
address?: string;
|
||||
bloodGroup?: string;
|
||||
admissionDate?: string;
|
||||
dischargeDate?: string;
|
||||
status: Status;
|
||||
}
|
||||
|
||||
export interface PatientRecordDto {
|
||||
id?: string;
|
||||
patientId?: string;
|
||||
patients: PatientDto;
|
||||
dateOfAdmission?: string;
|
||||
diagnosis?: string;
|
||||
treatmentPlan?: string;
|
||||
doctorNotes?: string;
|
||||
labReportUrl?: string;
|
||||
medicationUrl?: string;
|
||||
medicationHistoryUrl?: string;
|
||||
nextFollowUp?: string;
|
||||
insuranceProvider?: string;
|
||||
status: Status;
|
||||
}
|
3
angular/src/app/proxy/patients/index.ts
Normal file
3
angular/src/app/proxy/patients/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import * as Dto from './dto';
|
||||
export * from './patient.service';
|
||||
export { Dto };
|
124
angular/src/app/proxy/patients/patient.service.ts
Normal file
124
angular/src/app/proxy/patients/patient.service.ts
Normal file
@ -0,0 +1,124 @@
|
||||
import type { CreateUpdatePatientDto, CreateUpdatePatientRecordDto, PatientDto, PatientRecordDto } from './dto/models';
|
||||
import { RestService, Rest } from '@abp/ng.core';
|
||||
import type { PagedResultDto } from '@abp/ng.core';
|
||||
import { Injectable } from '@angular/core';
|
||||
import type { DropDownItems, FileDownloadDto, PagingSortPatientResultDto } from '../dto/models';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class PatientService {
|
||||
apiName = 'Default';
|
||||
|
||||
|
||||
createPatient = (input: CreateUpdatePatientDto, config?: Partial<Rest.Config>) =>
|
||||
this.restService.request<any, PatientDto>({
|
||||
method: 'POST',
|
||||
url: '/api/app/patient/patient',
|
||||
body: input,
|
||||
},
|
||||
{ apiName: this.apiName,...config });
|
||||
|
||||
|
||||
createPatientRecord = (input: CreateUpdatePatientRecordDto, config?: Partial<Rest.Config>) =>
|
||||
this.restService.request<any, PatientRecordDto>({
|
||||
method: 'POST',
|
||||
url: '/api/app/patient/patient-record',
|
||||
body: input,
|
||||
},
|
||||
{ apiName: this.apiName,...config });
|
||||
|
||||
|
||||
deletePatient = (id: string, config?: Partial<Rest.Config>) =>
|
||||
this.restService.request<any, void>({
|
||||
method: 'DELETE',
|
||||
url: `/api/app/patient/${id}/patient`,
|
||||
},
|
||||
{ apiName: this.apiName,...config });
|
||||
|
||||
|
||||
deletePatientRecord = (id: string, config?: Partial<Rest.Config>) =>
|
||||
this.restService.request<any, void>({
|
||||
method: 'DELETE',
|
||||
url: `/api/app/patient/${id}/patient-record`,
|
||||
},
|
||||
{ apiName: this.apiName,...config });
|
||||
|
||||
|
||||
getExportPatientData = (config?: Partial<Rest.Config>) =>
|
||||
this.restService.request<any, FileDownloadDto>({
|
||||
method: 'GET',
|
||||
url: '/api/app/patient/export-patient-data',
|
||||
},
|
||||
{ apiName: this.apiName,...config });
|
||||
|
||||
|
||||
getExportPatientRecord = (config?: Partial<Rest.Config>) =>
|
||||
this.restService.request<any, FileDownloadDto>({
|
||||
method: 'GET',
|
||||
url: '/api/app/patient/export-patient-record',
|
||||
},
|
||||
{ apiName: this.apiName,...config });
|
||||
|
||||
|
||||
getPatientById = (id: string, config?: Partial<Rest.Config>) =>
|
||||
this.restService.request<any, PatientDto>({
|
||||
method: 'GET',
|
||||
url: `/api/app/patient/${id}/patient-by-id`,
|
||||
},
|
||||
{ apiName: this.apiName,...config });
|
||||
|
||||
|
||||
getPatientList = (input: PagingSortPatientResultDto, config?: Partial<Rest.Config>) =>
|
||||
this.restService.request<any, PagedResultDto<PatientDto>>({
|
||||
method: 'GET',
|
||||
url: '/api/app/patient/patient-list',
|
||||
params: { search: input.search, sorting: input.sorting, skipCount: input.skipCount, maxResultCount: input.maxResultCount },
|
||||
},
|
||||
{ apiName: this.apiName,...config });
|
||||
|
||||
|
||||
getPatientRecordById = (id: string, config?: Partial<Rest.Config>) =>
|
||||
this.restService.request<any, PatientRecordDto>({
|
||||
method: 'GET',
|
||||
url: `/api/app/patient/${id}/patient-record-by-id`,
|
||||
},
|
||||
{ apiName: this.apiName,...config });
|
||||
|
||||
|
||||
getPatientRecordList = (input: PagingSortPatientResultDto, Id: string, config?: Partial<Rest.Config>) =>
|
||||
this.restService.request<any, PagedResultDto<PatientRecordDto>>({
|
||||
method: 'GET',
|
||||
url: `/api/app/patient/patient-record-list/${Id}`,
|
||||
params: { search: input.search, sorting: input.sorting, skipCount: input.skipCount, maxResultCount: input.maxResultCount },
|
||||
},
|
||||
{ apiName: this.apiName,...config });
|
||||
|
||||
|
||||
getStatusDropdown = (config?: Partial<Rest.Config>) =>
|
||||
this.restService.request<any, DropDownItems[]>({
|
||||
method: 'GET',
|
||||
url: '/api/app/patient/status-dropdown',
|
||||
},
|
||||
{ apiName: this.apiName,...config });
|
||||
|
||||
|
||||
updatePatient = (id: string, input: CreateUpdatePatientDto, config?: Partial<Rest.Config>) =>
|
||||
this.restService.request<any, PatientDto>({
|
||||
method: 'PUT',
|
||||
url: `/api/app/patient/${id}/patient`,
|
||||
body: input,
|
||||
},
|
||||
{ apiName: this.apiName,...config });
|
||||
|
||||
|
||||
updatePatientRecord = (id: string, input: CreateUpdatePatientRecordDto, config?: Partial<Rest.Config>) =>
|
||||
this.restService.request<any, PatientRecordDto>({
|
||||
method: 'PUT',
|
||||
url: `/api/app/patient/${id}/patient-record`,
|
||||
body: input,
|
||||
},
|
||||
{ apiName: this.apiName,...config });
|
||||
|
||||
constructor(private restService: RestService) {}
|
||||
}
|
@ -7,6 +7,7 @@ export const APP_ROUTE_PROVIDER = [
|
||||
|
||||
function configureRoutes(routesService: RoutesService) {
|
||||
return () => {
|
||||
|
||||
routesService.add([
|
||||
{
|
||||
path: '/',
|
||||
@ -15,6 +16,7 @@ function configureRoutes(routesService: RoutesService) {
|
||||
order: 1,
|
||||
layout: eLayoutType.application,
|
||||
},
|
||||
|
||||
{
|
||||
path: '/appointment',
|
||||
name: 'Appointments',
|
||||
@ -49,7 +51,31 @@ function configureRoutes(routesService: RoutesService) {
|
||||
parentName: 'Appointments',
|
||||
iconClass: 'fas fa-clock',
|
||||
order: 105,
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/patients',
|
||||
name: 'Patients',
|
||||
iconClass: 'fas fa-notes-medical',
|
||||
order: 201,
|
||||
layout: eLayoutType.application,
|
||||
requiredPolicy:'HospitalManagementSystem.Patient'
|
||||
},
|
||||
{
|
||||
path: '/patients/all-patients',
|
||||
name: 'All Patients',
|
||||
parentName: 'Patients',
|
||||
iconClass: 'fas fa-clock',
|
||||
order: 202,
|
||||
requiredPolicy:'HospitalManagementSystem.Patient'
|
||||
},
|
||||
// {
|
||||
// path: '/patients/patient-record',
|
||||
// name: 'Patient Record',
|
||||
// parentName: 'Patients',
|
||||
// iconClass: 'fas fa-clock',
|
||||
// order: 203,
|
||||
// requiredPolicy:'HospitalManagementSystem.Patient'
|
||||
// },
|
||||
]);
|
||||
};
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29020.237
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.9.34902.65
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HospitalManagementSystem.Domain", "src\HospitalManagementSystem.Domain\HospitalManagementSystem.Domain.csproj", "{554AD327-6DBA-4F8F-96F8-81CE7A0C863F}"
|
||||
EndProject
|
||||
@ -35,16 +35,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HospitalManagementSystem.Db
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HospitalManagementSystem.HttpApi.Host", "src\HospitalManagementSystem.HttpApi.Host\HospitalManagementSystem.HttpApi.Host.csproj", "{748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HospitalManagementSystem.Blazor.Client", "src\HospitalManagementSystem.Blazor.Client\HospitalManagementSystem.Blazor.Client.csproj", "{188A64AD-A1A7-4F95-85D1-C935594611B7}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HospitalManagementSystem.Blazor.WebApp", "src\HospitalManagementSystem.Blazor.WebApp\HospitalManagementSystem.Blazor.WebApp.csproj", "{14882ABF-1EEF-430C-8E72-812B3EE810C4}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HospitalManagementSystem.Blazor.WebApp.Client", "src\HospitalManagementSystem.Blazor.WebApp.Client\HospitalManagementSystem.Blazor.WebApp.Client.csproj", "{648460F4-3ECC-4751-9D87-EE25D0B8B2BF}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HospitalManagementSystem.Blazor.WebApp.Tiered", "src\HospitalManagementSystem.Blazor.WebApp.Tiered\HospitalManagementSystem.Blazor.WebApp.Tiered.csproj", "{8A3E5E20-F162-4321-8AD5-23DD7B2B0E74}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HospitalManagementSystem.Blazor.WebApp.Tiered.Client", "src\HospitalManagementSystem.Blazor.WebApp.Tiered.Client\HospitalManagementSystem.Blazor.WebApp.Tiered.Client.csproj", "{834C6A10-7562-427C-8771-B0588C35873D}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -107,26 +97,6 @@ Global
|
||||
{748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{188A64AD-A1A7-4F95-85D1-C935594611B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{188A64AD-A1A7-4F95-85D1-C935594611B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{188A64AD-A1A7-4F95-85D1-C935594611B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{188A64AD-A1A7-4F95-85D1-C935594611B7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{14882ABF-1EEF-430C-8E72-812B3EE810C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{14882ABF-1EEF-430C-8E72-812B3EE810C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{14882ABF-1EEF-430C-8E72-812B3EE810C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{14882ABF-1EEF-430C-8E72-812B3EE810C4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{648460F4-3ECC-4751-9D87-EE25D0B8B2BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{648460F4-3ECC-4751-9D87-EE25D0B8B2BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{648460F4-3ECC-4751-9D87-EE25D0B8B2BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{648460F4-3ECC-4751-9D87-EE25D0B8B2BF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8A3E5E20-F162-4321-8AD5-23DD7B2B0E74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8A3E5E20-F162-4321-8AD5-23DD7B2B0E74}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8A3E5E20-F162-4321-8AD5-23DD7B2B0E74}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8A3E5E20-F162-4321-8AD5-23DD7B2B0E74}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{834C6A10-7562-427C-8771-B0588C35873D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{834C6A10-7562-427C-8771-B0588C35873D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{834C6A10-7562-427C-8771-B0588C35873D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{834C6A10-7562-427C-8771-B0588C35873D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@ -146,11 +116,6 @@ Global
|
||||
{EF480016-9127-4916-8735-D2466BDBC582} = {04DBDB01-70F4-4E06-B468-8F87850B22BE}
|
||||
{AA94D832-1CCC-4715-95A9-A483F23A1A5D} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
|
||||
{748584B1-BA69-4F6A-81AA-F4BDE6BCE29D} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
|
||||
{188A64AD-A1A7-4F95-85D1-C935594611B7} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
|
||||
{14882ABF-1EEF-430C-8E72-812B3EE810C4} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
|
||||
{648460F4-3ECC-4751-9D87-EE25D0B8B2BF} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
|
||||
{8A3E5E20-F162-4321-8AD5-23DD7B2B0E74} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
|
||||
{834C6A10-7562-427C-8771-B0588C35873D} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {28315BFD-90E7-4E14-A2EA-F3D23AF4126F}
|
||||
|
@ -13,6 +13,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http.Features" Version="5.0.17" />
|
||||
<PackageReference Include="Volo.Abp.ObjectExtending" Version="9.0.2" />
|
||||
<PackageReference Include="Volo.Abp.Account.Application.Contracts" Version="9.0.2" />
|
||||
<PackageReference Include="Volo.Abp.Identity.Application.Contracts" Version="9.0.2" />
|
||||
|
@ -0,0 +1,27 @@
|
||||
using HospitalManagementSystem.GlobalEnum;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HospitalManagementSystem.Patients.Dto
|
||||
{
|
||||
public class CreateUpdatePatientDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public Gender Gender { get; set; }
|
||||
public string Mobile { get; set; }
|
||||
public string Email { get; set; }
|
||||
public int Age { get; set; }
|
||||
public string Treatment { get; set; }
|
||||
public string DoctorAssigned { get; set; }
|
||||
public string Address { get; set; }
|
||||
public string BloodGroup { get; set; }
|
||||
public DateTime AdmissionDate { get; set; }
|
||||
public DateTime? DischargeDate { get; set; }
|
||||
public Status Status { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
using HospitalManagementSystem.GlobalEnum;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HospitalManagementSystem.Patients.Dto
|
||||
{
|
||||
public class CreateUpdatePatientRecordDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
|
||||
//public string FullName { get; set; }
|
||||
|
||||
//public string Mobile { get; set; }
|
||||
|
||||
//public Gender Gender { get; set; }
|
||||
|
||||
public Guid PatientId { get; set; }
|
||||
|
||||
public DateTime DateOfAdmission { get; set; }
|
||||
|
||||
public string? LabReportUrl { get; set; }
|
||||
|
||||
public string? MedicationUrl { get; set; }
|
||||
|
||||
public string? MedicationHistoryUrl { get; set; }
|
||||
|
||||
public DateTime? NextFollowUp { get; set; }
|
||||
|
||||
public string Diagnosis { get; set; }
|
||||
|
||||
public string TreatmentPlan { get; set; }
|
||||
|
||||
public string DoctorNotes { get; set; }
|
||||
|
||||
public string InsuranceProvider { get; set; }
|
||||
|
||||
public Status Status { get; set; }
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
using HospitalManagementSystem.GlobalEnum;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HospitalManagementSystem.Patients.Dto
|
||||
{
|
||||
public class PatientDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public Gender Gender { get; set; }
|
||||
public string Mobile { get; set; }
|
||||
public string Email { get; set; }
|
||||
public int Age { get; set; }
|
||||
public string Treatment { get; set; }
|
||||
public string DoctorAssigned { get; set; }
|
||||
public string Address { get; set; }
|
||||
public string BloodGroup { get; set; }
|
||||
public DateTime AdmissionDate { get; set; }
|
||||
public DateTime? DischargeDate { get; set; }
|
||||
public Status Status { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
using HospitalManagementSystem.GlobalEnum;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static HospitalManagementSystem.Permissions.HospitalManagementSystemPermissions;
|
||||
using HospitalManagementSystem.Patients;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace HospitalManagementSystem.Patients.Dto
|
||||
{
|
||||
public class PatientRecordDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
|
||||
//public string FullName { get; set; }
|
||||
|
||||
//public string Mobile { get; set; }
|
||||
|
||||
//public Gender Gender { get; set; }
|
||||
|
||||
public Guid PatientId { get; set; }
|
||||
|
||||
public PatientDto Patients { get; set; }
|
||||
|
||||
public DateTime DateOfAdmission { get; set; }
|
||||
|
||||
public string Diagnosis { get; set; }
|
||||
|
||||
public string TreatmentPlan { get; set; }
|
||||
|
||||
public string DoctorNotes { get; set; }
|
||||
|
||||
public string LabReportUrl { get; set; }
|
||||
|
||||
public string MedicationUrl { get; set; }
|
||||
|
||||
public string MedicationHistoryUrl { get; set; }
|
||||
|
||||
public DateTime? NextFollowUp { get; set; }
|
||||
|
||||
public string InsuranceProvider { get; set; }
|
||||
|
||||
public Status Status { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -8,7 +8,12 @@ public class HospitalManagementSystemPermissionDefinitionProvider : PermissionDe
|
||||
{
|
||||
public override void Define(IPermissionDefinitionContext context)
|
||||
{
|
||||
var myGroup = context.AddGroup(HospitalManagementSystemPermissions.GroupName);
|
||||
var HostipalManagementGroup = context.AddGroup(HospitalManagementSystemPermissions.GroupName);
|
||||
|
||||
var PatientPermission = HostipalManagementGroup.AddPermission(HospitalManagementSystemPermissions.Patient.Default);
|
||||
PatientPermission.AddChild(HospitalManagementSystemPermissions.Patient.Create);
|
||||
PatientPermission.AddChild(HospitalManagementSystemPermissions.Patient.Edit);
|
||||
PatientPermission.AddChild(HospitalManagementSystemPermissions.Patient.Delete);
|
||||
//Define your own permissions here. Example:
|
||||
//myGroup.AddPermission(HospitalManagementSystemPermissions.MyPermission1, L("Permission:MyPermission1"));
|
||||
}
|
||||
|
@ -6,4 +6,11 @@ public static class HospitalManagementSystemPermissions
|
||||
|
||||
//Add your own permission names. Example:
|
||||
//public const string MyPermission1 = GroupName + ".MyPermission1";
|
||||
public static class Patient
|
||||
{
|
||||
public const string Default = GroupName + ".Patient";
|
||||
public const string Create = Default + ".Create";
|
||||
public const string Edit = Default + ".Edit";
|
||||
public const string Delete = Default + ".Delete";
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Import Project="..\..\common.props" />
|
||||
|
||||
@ -11,9 +11,13 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\HospitalManagementSystem.Domain\HospitalManagementSystem.Domain.csproj" />
|
||||
<ProjectReference Include="..\HospitalManagementSystem.Application.Contracts\HospitalManagementSystem.Application.Contracts.csproj" />
|
||||
<ProjectReference Include="..\HospitalManagementSystem.HttpApi\HospitalManagementSystem.HttpApi.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Abp" Version="10.0.0" />
|
||||
<PackageReference Include="ClosedXML" Version="0.104.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.1" />
|
||||
<PackageReference Include="Volo.Abp.Account.Application" Version="9.0.2" />
|
||||
<PackageReference Include="Volo.Abp.Identity.Application" Version="9.0.2" />
|
||||
<PackageReference Include="Volo.Abp.PermissionManagement.Application" Version="9.0.2" />
|
||||
|
@ -0,0 +1,31 @@
|
||||
using AutoMapper;
|
||||
using HospitalManagementSystem.Patients;
|
||||
using HospitalManagementSystem.Patients.Dto;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HospitalManagementSystem
|
||||
{
|
||||
public class PatientAutoMapperProfile : Profile
|
||||
{
|
||||
public PatientAutoMapperProfile()
|
||||
{
|
||||
// Entity to DTO mappings
|
||||
CreateMap<PatientRecord, PatientRecordDto>();
|
||||
CreateMap<PatientRecord, CreateUpdatePatientRecordDto>();
|
||||
|
||||
// DTO to Entity mappings
|
||||
CreateMap<CreateUpdatePatientRecordDto, PatientRecord>();
|
||||
|
||||
// Entity to DTO mappings
|
||||
CreateMap<Patient, PatientDto>();
|
||||
CreateMap<Patient, CreateUpdatePatientDto>();
|
||||
|
||||
// DTO to Entity mappings
|
||||
CreateMap<CreateUpdatePatientDto, Patient>();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,347 @@
|
||||
using ClosedXML.Excel;
|
||||
using HospitalManagementSystem.Dto;
|
||||
using HospitalManagementSystem.GlobalEnum;
|
||||
using HospitalManagementSystem.Patients.Dto;
|
||||
using HospitalManagementSystem.Permissions;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using System.Threading.Tasks;
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Volo.Abp.Application.Services;
|
||||
using Volo.Abp.Domain.Repositories;
|
||||
|
||||
|
||||
namespace HospitalManagementSystem.Patients
|
||||
{
|
||||
public class PatientAppService : ApplicationService
|
||||
{
|
||||
private IRepository<PatientRecord, Guid> _patientrecordRepository;
|
||||
private IRepository<Patient, Guid> _patientRepository;
|
||||
|
||||
public PatientAppService(IRepository<PatientRecord, Guid> patientrecordRepository, IRepository<Patient, Guid> patientRepository)
|
||||
{
|
||||
_patientrecordRepository = patientrecordRepository;
|
||||
_patientRepository = patientRepository;
|
||||
}
|
||||
|
||||
#region PatientRecord
|
||||
|
||||
#region Get Patient List with Paging and Searching
|
||||
[Authorize(HospitalManagementSystemPermissions.Patient.Default)]
|
||||
public async Task<PagedResultDto<PatientRecordDto>> GetPatientRecordListAsync(PagingSortPatientResultDto input, Guid Id)
|
||||
{
|
||||
//List<PatientRecord>? query;
|
||||
|
||||
//query = _patientrecordRepository.GetQueryableAsync().Result
|
||||
// .Include(x => x.Patients)
|
||||
// .WhereIf(!String.IsNullOrEmpty(input.Search), x => x.Patients.Name.ToLower().Contains(input.Search.ToLower()))
|
||||
// .Where(x => x.Patients.Id == Id)
|
||||
// .OrderBy(input.Sorting ?? (nameof(PatientRecord.Id) + " asc"))
|
||||
// .Skip(input.SkipCount)
|
||||
// .Take(input.MaxResultCount)
|
||||
// .ToList();
|
||||
|
||||
//var totalCount = await _patientrecordRepository.CountAsync();
|
||||
//return new PagedResultDto<PatientRecordDto>(
|
||||
// totalCount,
|
||||
// ObjectMapper.Map<List<PatientRecord>, List<PatientRecordDto>>(query)
|
||||
//);
|
||||
var queryable = await _patientrecordRepository.GetQueryableAsync();
|
||||
|
||||
var filteredQuery = queryable
|
||||
.Include(x => x.Patients)
|
||||
.WhereIf(!string.IsNullOrEmpty(input.Search), x => x.Patients.Name.ToLower().Contains(input.Search.ToLower()))
|
||||
.Where(x => x.Patients.Id == Id);
|
||||
|
||||
// Get total count after filtering
|
||||
var totalCount = await filteredQuery.CountAsync();
|
||||
|
||||
// Apply sorting dynamically (ensure input.Sorting is valid)
|
||||
filteredQuery = !string.IsNullOrEmpty(input.Sorting)
|
||||
? filteredQuery.OrderBy(input.Sorting)
|
||||
: filteredQuery.OrderBy(x => x.Id);
|
||||
|
||||
// Apply paging
|
||||
var pagedQuery = await filteredQuery
|
||||
.Skip(input.SkipCount)
|
||||
.Take(input.MaxResultCount)
|
||||
.ToListAsync();
|
||||
|
||||
return new PagedResultDto<PatientRecordDto>(
|
||||
totalCount,
|
||||
ObjectMapper.Map<List<PatientRecord>, List<PatientRecordDto>>(pagedQuery)
|
||||
);
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Get Single Patient by Id
|
||||
[Authorize(HospitalManagementSystemPermissions.Patient.Default)]
|
||||
public async Task<PatientRecordDto> GetPatientRecordByIdAsync(Guid id)
|
||||
{
|
||||
var patient = await _patientrecordRepository.GetAsync(id);
|
||||
return ObjectMapper.Map<PatientRecord, PatientRecordDto>(patient);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Export Patient Data to Excel
|
||||
public async Task<FileDownloadDto> GetExportPatientRecordAsync()
|
||||
{
|
||||
var patients = await _patientrecordRepository.GetListAsync();
|
||||
|
||||
var folderPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "exports");
|
||||
if (!Directory.Exists(folderPath))
|
||||
{
|
||||
Directory.CreateDirectory(folderPath); // Ensure the folder exists
|
||||
}
|
||||
|
||||
var filename = "Patients_" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".xlsx";
|
||||
var filePath = Path.Combine(folderPath, filename);
|
||||
|
||||
// Create a workbook and worksheet
|
||||
using (var workbook = new XLWorkbook())
|
||||
{
|
||||
var worksheet = workbook.Worksheets.Add("Patients");
|
||||
|
||||
// Add headers
|
||||
worksheet.Cell(1, 1).Value = "Full Name";
|
||||
worksheet.Cell(1, 2).Value = "Gender";
|
||||
worksheet.Cell(1, 3).Value = "Date of Admission";
|
||||
worksheet.Cell(1, 4).Value = "Diagnosis";
|
||||
worksheet.Cell(1, 5).Value = "Next Follow-Up";
|
||||
worksheet.Cell(1, 6).Value = "Status";
|
||||
|
||||
for (int i = 0; i < patients.Count; i++)
|
||||
{
|
||||
worksheet.Cell(i + 2, 1).Value = patients[i].Patients.Name;
|
||||
worksheet.Cell(i + 2, 2).Value = patients[i].Patients.Gender.ToString();
|
||||
worksheet.Cell(i + 2, 3).Value = patients[i].DateOfAdmission.ToShortDateString();
|
||||
worksheet.Cell(i + 2, 4).Value = patients[i].Diagnosis;
|
||||
worksheet.Cell(i + 2, 5).Value = patients[i].NextFollowUp?.ToShortDateString();
|
||||
worksheet.Cell(i + 2, 6).Value = patients[i].Status.ToString();
|
||||
}
|
||||
|
||||
worksheet.Columns().AdjustToContents();
|
||||
workbook.SaveAs(filePath);
|
||||
}
|
||||
|
||||
byte[] fileBytes = await File.ReadAllBytesAsync(filePath);
|
||||
File.Delete(filePath);
|
||||
|
||||
return new FileDownloadDto
|
||||
{
|
||||
FileName = filename,
|
||||
FileContent = Convert.ToBase64String(fileBytes) // Use Base64 encoding for file content
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Create Patient
|
||||
[Authorize(HospitalManagementSystemPermissions.Patient.Create)]
|
||||
public async Task<PatientRecordDto> CreatePatientRecordAsync(CreateUpdatePatientRecordDto input)
|
||||
{
|
||||
var patientEntity = await _patientRepository.GetAsync(input.PatientId); // Get Patient from DB
|
||||
|
||||
var patientRecord = ObjectMapper.Map<CreateUpdatePatientRecordDto, PatientRecord>(input);
|
||||
patientRecord.Patients = patientEntity; // Assign the fetched entity
|
||||
|
||||
patientRecord = await _patientrecordRepository.InsertAsync(patientRecord);
|
||||
|
||||
return ObjectMapper.Map<PatientRecord, PatientRecordDto>(patientRecord);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Update Patient
|
||||
[Authorize(HospitalManagementSystemPermissions.Patient.Edit)]
|
||||
public async Task<PatientRecordDto> UpdatePatientRecordAsync(Guid id, CreateUpdatePatientRecordDto input)
|
||||
{
|
||||
var patientRecord = await _patientrecordRepository.GetAsync(id);
|
||||
|
||||
if (patientRecord.Patients.Id != input.PatientId) // If PatientId is updated, fetch new Patient
|
||||
{
|
||||
var newPatient = await _patientRepository.GetAsync(input.PatientId);
|
||||
patientRecord.Patients = newPatient;
|
||||
}
|
||||
|
||||
ObjectMapper.Map(input, patientRecord);
|
||||
|
||||
patientRecord = await _patientrecordRepository.UpdateAsync(patientRecord);
|
||||
|
||||
return ObjectMapper.Map<PatientRecord, PatientRecordDto>(patientRecord);
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Delete Patient
|
||||
[Authorize(HospitalManagementSystemPermissions.Patient.Delete)]
|
||||
public async Task DeletePatientRecordAsync(Guid id)
|
||||
{
|
||||
await _patientrecordRepository.DeleteAsync(id);
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Patient
|
||||
|
||||
#region Get Patient List with Paging and Searching
|
||||
[Authorize(HospitalManagementSystemPermissions.Patient.Default)]
|
||||
public async Task<PagedResultDto<PatientDto>> GetPatientListAsync(PagingSortPatientResultDto input)
|
||||
{
|
||||
List<Patient> query;
|
||||
|
||||
if (!string.IsNullOrEmpty(input.Search))
|
||||
{
|
||||
query = _patientRepository.GetQueryableAsync().Result
|
||||
.Where(x => x.Name.ToLower().Contains(input.Search.ToLower()))
|
||||
.OrderBy(input.Sorting ?? (nameof(Patient.Id) + " asc"))
|
||||
.Skip(input.SkipCount)
|
||||
.Take(input.MaxResultCount)
|
||||
.ToList();
|
||||
}
|
||||
else
|
||||
{
|
||||
query = await _patientRepository.GetPagedListAsync(
|
||||
input.SkipCount,
|
||||
input.MaxResultCount,
|
||||
input.Sorting ?? nameof(Patient.Name)
|
||||
);
|
||||
}
|
||||
|
||||
var totalCount = await _patientRepository.CountAsync();
|
||||
return new PagedResultDto<PatientDto>(
|
||||
totalCount,
|
||||
ObjectMapper.Map<List<Patient>, List<PatientDto>>(query)
|
||||
);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Get Single Patient by Id
|
||||
[Authorize(HospitalManagementSystemPermissions.Patient.Default)]
|
||||
public async Task<PatientDto> GetPatientByIdAsync(Guid id)
|
||||
{
|
||||
var patient = await _patientRepository.GetAsync(id);
|
||||
return ObjectMapper.Map<Patient, PatientDto>(patient);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Export Patient Data to Excel
|
||||
public async Task<FileDownloadDto> GetExportPatientDataAsync()
|
||||
{
|
||||
var patients = await _patientRepository.GetListAsync();
|
||||
|
||||
var folderPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "exports");
|
||||
if (!Directory.Exists(folderPath))
|
||||
{
|
||||
Directory.CreateDirectory(folderPath);
|
||||
}
|
||||
|
||||
var filename = "Patients_" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".xlsx";
|
||||
var filePath = Path.Combine(folderPath, filename);
|
||||
|
||||
using (var workbook = new XLWorkbook())
|
||||
{
|
||||
var worksheet = workbook.Worksheets.Add("Patients");
|
||||
|
||||
// Add headers
|
||||
worksheet.Cell(1, 1).Value = "Name";
|
||||
worksheet.Cell(1, 2).Value = "Gender";
|
||||
worksheet.Cell(1, 3).Value = "Age";
|
||||
worksheet.Cell(1, 4).Value = "Treatment";
|
||||
worksheet.Cell(1, 5).Value = "Doctor Assigned";
|
||||
worksheet.Cell(1, 6).Value = "Admission Date";
|
||||
worksheet.Cell(1, 7).Value = "Discharge Date";
|
||||
worksheet.Cell(1, 8).Value = "Status";
|
||||
|
||||
// Add data rows
|
||||
for (int i = 0; i < patients.Count; i++)
|
||||
{
|
||||
worksheet.Cell(i + 2, 1).Value = patients[i].Name;
|
||||
worksheet.Cell(i + 2, 2).Value = patients[i].Gender.ToString();
|
||||
worksheet.Cell(i + 2, 3).Value = patients[i].Age;
|
||||
worksheet.Cell(i + 2, 4).Value = patients[i].Treatment;
|
||||
worksheet.Cell(i + 2, 5).Value = patients[i].DoctorAssigned;
|
||||
worksheet.Cell(i + 2, 6).Value = patients[i].AdmissionDate.ToShortDateString();
|
||||
worksheet.Cell(i + 2, 7).Value = patients[i].DischargeDate?.ToShortDateString();
|
||||
worksheet.Cell(i + 2, 8).Value = patients[i].Status.ToString();
|
||||
}
|
||||
|
||||
worksheet.Columns().AdjustToContents();
|
||||
workbook.SaveAs(filePath);
|
||||
}
|
||||
|
||||
byte[] fileBytes = await File.ReadAllBytesAsync(filePath);
|
||||
File.Delete(filePath);
|
||||
|
||||
return new FileDownloadDto
|
||||
{
|
||||
FileName = filename,
|
||||
FileContent = Convert.ToBase64String(fileBytes)
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Create Patient
|
||||
[Authorize(HospitalManagementSystemPermissions.Patient.Create)]
|
||||
public async Task<PatientDto> CreatePatientAsync(CreateUpdatePatientDto input)
|
||||
{
|
||||
var patient = ObjectMapper.Map<CreateUpdatePatientDto, Patient>(input);
|
||||
|
||||
patient = await _patientRepository.InsertAsync(patient);
|
||||
return ObjectMapper.Map<Patient, PatientDto>(patient);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Update Patient
|
||||
[Authorize(HospitalManagementSystemPermissions.Patient.Edit)]
|
||||
public async Task<PatientDto> UpdatePatientAsync(Guid id, CreateUpdatePatientDto input)
|
||||
{
|
||||
var patient = await _patientRepository.GetAsync(id);
|
||||
|
||||
ObjectMapper.Map(input, patient);
|
||||
|
||||
patient = await _patientRepository.UpdateAsync(patient);
|
||||
return ObjectMapper.Map<Patient, PatientDto>(patient);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Delete Patient
|
||||
[Authorize(HospitalManagementSystemPermissions.Patient.Delete)]
|
||||
public async Task DeletePatientAsync(Guid id)
|
||||
{
|
||||
await _patientRepository.DeleteAsync(id);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Get Status Dropdown
|
||||
public async Task<List<DropDownItems>> GetStatusDropdownAsync()
|
||||
{
|
||||
List<DropDownItems> statuslist = new List<DropDownItems>();
|
||||
|
||||
statuslist = Enum.GetValues(typeof(Status))
|
||||
.Cast<Status>()
|
||||
.Select(e => new DropDownItems
|
||||
{
|
||||
Label = e.ToString(),
|
||||
Value = (int)e
|
||||
})
|
||||
.ToList();
|
||||
statuslist.Add(new DropDownItems
|
||||
{
|
||||
Label = "Select a Status",
|
||||
Value = 0
|
||||
});
|
||||
statuslist = statuslist.OrderBy(x => x.Value).ToList();
|
||||
|
||||
return await Task.FromResult(statuslist);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HospitalManagementSystem.Dto
|
||||
{
|
||||
public class DropDownItems
|
||||
{
|
||||
public string Label { get; set; }
|
||||
public int Value { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HospitalManagementSystem.Dto
|
||||
{
|
||||
public class FileDownloadDto
|
||||
{
|
||||
public string FileName { get; set; }
|
||||
|
||||
public string FileContent { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Volo.Abp.Application.Dtos;
|
||||
|
||||
namespace HospitalManagementSystem.Dto
|
||||
{
|
||||
public class PagingSortPatientResultDto : PagedAndSortedResultRequestDto
|
||||
{
|
||||
public string? Search { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HospitalManagementSystem.Dto
|
||||
{
|
||||
using System.Linq.Dynamic.Core;
|
||||
|
||||
public static class QueryableExtensions
|
||||
{
|
||||
public static IEnumerable<T> OrderByDynamic<T>(this IEnumerable<T> source, string orderBy)
|
||||
{
|
||||
return source.AsQueryable().OrderBy(orderBy);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HospitalManagementSystem.GlobalEnum
|
||||
{
|
||||
public enum Gender
|
||||
{
|
||||
Male = 1,
|
||||
Female = 2
|
||||
}
|
||||
|
||||
public enum Status
|
||||
{
|
||||
Recovered = 1,
|
||||
Observation = 2,
|
||||
InTreatment = 3
|
||||
}
|
||||
|
||||
}
|
@ -10,6 +10,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="9.0.2" />
|
||||
<PackageReference Include="Volo.Abp.Identity.Domain.Shared" Version="9.0.2" />
|
||||
<PackageReference Include="Volo.Abp.BackgroundJobs.Domain.Shared" Version="9.0.2" />
|
||||
<PackageReference Include="Volo.Abp.AuditLogging.Domain.Shared" Version="9.0.2" />
|
||||
|
@ -4,6 +4,7 @@
|
||||
"AppName": "HospitalManagementSystem",
|
||||
"Menu:Home": "Home",
|
||||
"Welcome": "Welcome",
|
||||
"LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io."
|
||||
"LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io.",
|
||||
"PatientHeader": "Patient Records"
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,36 @@
|
||||
using HospitalManagementSystem.GlobalEnum;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Volo.Abp.Domain.Entities.Auditing;
|
||||
|
||||
namespace HospitalManagementSystem.Patients
|
||||
{
|
||||
public class Patient : AuditedAggregateRoot<Guid>
|
||||
{
|
||||
[Required]
|
||||
public string Name { get; set; }
|
||||
[Required]
|
||||
public Gender Gender { get; set; }
|
||||
[Required]
|
||||
public string Mobile { get; set; }
|
||||
[Required]
|
||||
public string Email { get; set; }
|
||||
[Required]
|
||||
public int Age { get; set; }
|
||||
public string Treatment { get; set; }
|
||||
public string DoctorAssigned { get; set; }
|
||||
[Required]
|
||||
public string Address { get; set; }
|
||||
[Required]
|
||||
public string BloodGroup { get; set; }
|
||||
public DateTime AdmissionDate { get; set; }
|
||||
public DateTime? DischargeDate { get; set; }
|
||||
[Required]
|
||||
public Status Status { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Volo.Abp.Domain.Entities.Auditing;
|
||||
using System.Threading.Tasks;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using HospitalManagementSystem.GlobalEnum;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace HospitalManagementSystem.Patients
|
||||
{
|
||||
public class PatientRecord : AuditedAggregateRoot<Guid>
|
||||
{
|
||||
//[Required]
|
||||
//public string FullName { get; set; }
|
||||
|
||||
//[Required]
|
||||
//public string Mobile { get; set; }
|
||||
|
||||
//[Required]
|
||||
//public Gender Gender { get; set; }
|
||||
public virtual Patient Patients { get; set; }
|
||||
|
||||
[Required]
|
||||
public DateTime DateOfAdmission { get; set; }
|
||||
|
||||
public string Diagnosis { get; set; }
|
||||
|
||||
public string TreatmentPlan { get; set; }
|
||||
|
||||
public string DoctorNotes { get; set; }
|
||||
|
||||
public string? LabReportUrl { get; set; }
|
||||
|
||||
public string? MedicationUrl { get; set; }
|
||||
|
||||
public string? MedicationHistoryUrl { get; set; }
|
||||
|
||||
public DateTime? NextFollowUp { get; set; }
|
||||
|
||||
public string InsuranceProvider { get; set; }
|
||||
|
||||
[Required]
|
||||
public Status Status { get; set; }
|
||||
}
|
||||
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using HospitalManagementSystem.Patients;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Volo.Abp.AuditLogging.EntityFrameworkCore;
|
||||
using Volo.Abp.BackgroundJobs.EntityFrameworkCore;
|
||||
using Volo.Abp.Data;
|
||||
using Volo.Abp.DependencyInjection;
|
||||
using Volo.Abp.EntityFrameworkCore;
|
||||
using Volo.Abp.EntityFrameworkCore.Modeling;
|
||||
using Volo.Abp.FeatureManagement.EntityFrameworkCore;
|
||||
using Volo.Abp.Identity;
|
||||
using Volo.Abp.Identity.EntityFrameworkCore;
|
||||
@ -24,7 +26,8 @@ public class HospitalManagementSystemDbContext :
|
||||
ITenantManagementDbContext
|
||||
{
|
||||
/* Add DbSet properties for your Aggregate Roots / Entities here. */
|
||||
|
||||
public DbSet<PatientRecord> PatientRecords { get; set; }
|
||||
public DbSet<Patient> Patients { get; set; }
|
||||
#region Entities from the modules
|
||||
|
||||
/* Notice: We only implemented IIdentityDbContext and ITenantManagementDbContext
|
||||
@ -75,6 +78,17 @@ public class HospitalManagementSystemDbContext :
|
||||
builder.ConfigureTenantManagement();
|
||||
|
||||
/* Configure your own tables/entities inside here */
|
||||
builder.Entity<PatientRecord>(b =>
|
||||
{
|
||||
b.ToTable("PatientRecords");
|
||||
b.ConfigureByConvention();//auto configure for the base class props
|
||||
});
|
||||
|
||||
builder.Entity<Patient>(b =>
|
||||
{
|
||||
b.ToTable("Patient");
|
||||
b.ConfigureByConvention(); //auto configure for the base class props
|
||||
});
|
||||
|
||||
//builder.Entity<YourEntity>(b =>
|
||||
//{
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace HospitalManagementSystem.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class added_patientinpatientrecord : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Patient",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
Name = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
Gender = table.Column<int>(type: "int", nullable: false),
|
||||
Mobile = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
Email = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
Age = table.Column<int>(type: "int", nullable: false),
|
||||
Treatment = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
DoctorAssigned = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
Address = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
BloodGroup = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
AdmissionDate = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||
DischargeDate = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
Status = table.Column<int>(type: "int", nullable: false),
|
||||
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false),
|
||||
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Patient", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "PatientRecords",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
PatientsId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
|
||||
DateOfAdmission = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||
Diagnosis = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
TreatmentPlan = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
DoctorNotes = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
LabReportUrl = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
MedicationUrl = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
MedicationHistoryUrl = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||
NextFollowUp = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
InsuranceProvider = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
Status = table.Column<int>(type: "int", nullable: false),
|
||||
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false),
|
||||
CreationTime = table.Column<DateTime>(type: "datetime2", nullable: false),
|
||||
CreatorId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
|
||||
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||
LastModifierId = table.Column<Guid>(type: "uniqueidentifier", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_PatientRecords", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_PatientRecords_Patient_PatientsId",
|
||||
column: x => x.PatientsId,
|
||||
principalTable: "Patient",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PatientRecords_PatientsId",
|
||||
table: "PatientRecords",
|
||||
column: "PatientsId");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "PatientRecords");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Patient");
|
||||
}
|
||||
}
|
||||
}
|
@ -24,6 +24,164 @@ namespace HospitalManagementSystem.Migrations
|
||||
|
||||
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("HospitalManagementSystem.Patients.Patient", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("Address")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<DateTime>("AdmissionDate")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<int>("Age")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("BloodGroup")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.IsRequired()
|
||||
.HasMaxLength(40)
|
||||
.HasColumnType("nvarchar(40)")
|
||||
.HasColumnName("ConcurrencyStamp");
|
||||
|
||||
b.Property<DateTime>("CreationTime")
|
||||
.HasColumnType("datetime2")
|
||||
.HasColumnName("CreationTime");
|
||||
|
||||
b.Property<Guid?>("CreatorId")
|
||||
.HasColumnType("uniqueidentifier")
|
||||
.HasColumnName("CreatorId");
|
||||
|
||||
b.Property<DateTime?>("DischargeDate")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<string>("DoctorAssigned")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("ExtraProperties")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("ExtraProperties");
|
||||
|
||||
b.Property<int>("Gender")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<DateTime?>("LastModificationTime")
|
||||
.HasColumnType("datetime2")
|
||||
.HasColumnName("LastModificationTime");
|
||||
|
||||
b.Property<Guid?>("LastModifierId")
|
||||
.HasColumnType("uniqueidentifier")
|
||||
.HasColumnName("LastModifierId");
|
||||
|
||||
b.Property<string>("Mobile")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Treatment")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Patient", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("HospitalManagementSystem.Patients.PatientRecord", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.IsRequired()
|
||||
.HasMaxLength(40)
|
||||
.HasColumnType("nvarchar(40)")
|
||||
.HasColumnName("ConcurrencyStamp");
|
||||
|
||||
b.Property<DateTime>("CreationTime")
|
||||
.HasColumnType("datetime2")
|
||||
.HasColumnName("CreationTime");
|
||||
|
||||
b.Property<Guid?>("CreatorId")
|
||||
.HasColumnType("uniqueidentifier")
|
||||
.HasColumnName("CreatorId");
|
||||
|
||||
b.Property<DateTime>("DateOfAdmission")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<string>("Diagnosis")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("DoctorNotes")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("ExtraProperties")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)")
|
||||
.HasColumnName("ExtraProperties");
|
||||
|
||||
b.Property<string>("InsuranceProvider")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("LabReportUrl")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<DateTime?>("LastModificationTime")
|
||||
.HasColumnType("datetime2")
|
||||
.HasColumnName("LastModificationTime");
|
||||
|
||||
b.Property<Guid?>("LastModifierId")
|
||||
.HasColumnType("uniqueidentifier")
|
||||
.HasColumnName("LastModifierId");
|
||||
|
||||
b.Property<string>("MedicationHistoryUrl")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("MedicationUrl")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<DateTime?>("NextFollowUp")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
b.Property<Guid>("PatientsId")
|
||||
.HasColumnType("uniqueidentifier");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("TreatmentPlan")
|
||||
.IsRequired()
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PatientsId");
|
||||
|
||||
b.ToTable("PatientRecords", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLog", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@ -1764,6 +1922,17 @@ namespace HospitalManagementSystem.Migrations
|
||||
b.ToTable("AbpTenantConnectionStrings", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("HospitalManagementSystem.Patients.PatientRecord", b =>
|
||||
{
|
||||
b.HasOne("HospitalManagementSystem.Patients.Patient", "Patients")
|
||||
.WithMany()
|
||||
.HasForeignKey("PatientsId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Patients");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Volo.Abp.AuditLogging.AuditLogAction", b =>
|
||||
{
|
||||
b.HasOne("Volo.Abp.AuditLogging.AuditLog", null)
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
56
aspnet-core/src/HospitalManagementSystem.HttpApi.Host/wwwroot/libs/abp/core/abp.css
vendored
Normal file
56
aspnet-core/src/HospitalManagementSystem.HttpApi.Host/wwwroot/libs/abp/core/abp.css
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: translateZ(0) rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateZ(0) rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.abp-block-area {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 102;
|
||||
background-color: #fff;
|
||||
opacity: .8;
|
||||
transition: opacity .25s;
|
||||
}
|
||||
|
||||
.abp-block-area.abp-block-area-disappearing {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.abp-block-area.abp-block-area-busy:after {
|
||||
content: attr(data-text);
|
||||
display: block;
|
||||
max-width: 125px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
font-size: 20px;
|
||||
font-family: sans-serif;
|
||||
color: #343a40;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.abp-block-area.abp-block-area-busy:before {
|
||||
content: "";
|
||||
display: block;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
border-radius: 50%;
|
||||
border-width: 2px;
|
||||
border-style: solid;
|
||||
border-color: transparent #228ae6 #228ae6 #228ae6;
|
||||
position: absolute;
|
||||
top: calc(50% - 75px);
|
||||
left: calc(50% - 75px);
|
||||
will-change: transform;
|
||||
animation: spin .75s infinite ease-in-out;
|
||||
}
|
827
aspnet-core/src/HospitalManagementSystem.HttpApi.Host/wwwroot/libs/abp/core/abp.js
vendored
Normal file
827
aspnet-core/src/HospitalManagementSystem.HttpApi.Host/wwwroot/libs/abp/core/abp.js
vendored
Normal file
@ -0,0 +1,827 @@
|
||||
var abp = abp || {};
|
||||
(function () {
|
||||
|
||||
/* Application paths *****************************************/
|
||||
|
||||
//Current application root path (including virtual directory if exists).
|
||||
abp.appPath = abp.appPath || '/';
|
||||
|
||||
abp.pageLoadTime = new Date();
|
||||
|
||||
//Converts given path to absolute path using abp.appPath variable.
|
||||
abp.toAbsAppPath = function (path) {
|
||||
if (path.indexOf('/') == 0) {
|
||||
path = path.substring(1);
|
||||
}
|
||||
|
||||
return abp.appPath + path;
|
||||
};
|
||||
|
||||
/* LOGGING ***************************************************/
|
||||
//Implements Logging API that provides secure & controlled usage of console.log
|
||||
|
||||
abp.log = abp.log || {};
|
||||
|
||||
abp.log.levels = {
|
||||
DEBUG: 1,
|
||||
INFO: 2,
|
||||
WARN: 3,
|
||||
ERROR: 4,
|
||||
FATAL: 5
|
||||
};
|
||||
|
||||
abp.log.level = abp.log.levels.DEBUG;
|
||||
|
||||
abp.log.log = function (logObject, logLevel) {
|
||||
if (!window.console || !window.console.log) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (logLevel != undefined && logLevel < abp.log.level) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(logObject);
|
||||
};
|
||||
|
||||
abp.log.debug = function (logObject) {
|
||||
abp.log.log("DEBUG: ", abp.log.levels.DEBUG);
|
||||
abp.log.log(logObject, abp.log.levels.DEBUG);
|
||||
};
|
||||
|
||||
abp.log.info = function (logObject) {
|
||||
abp.log.log("INFO: ", abp.log.levels.INFO);
|
||||
abp.log.log(logObject, abp.log.levels.INFO);
|
||||
};
|
||||
|
||||
abp.log.warn = function (logObject) {
|
||||
abp.log.log("WARN: ", abp.log.levels.WARN);
|
||||
abp.log.log(logObject, abp.log.levels.WARN);
|
||||
};
|
||||
|
||||
abp.log.error = function (logObject) {
|
||||
abp.log.log("ERROR: ", abp.log.levels.ERROR);
|
||||
abp.log.log(logObject, abp.log.levels.ERROR);
|
||||
};
|
||||
|
||||
abp.log.fatal = function (logObject) {
|
||||
abp.log.log("FATAL: ", abp.log.levels.FATAL);
|
||||
abp.log.log(logObject, abp.log.levels.FATAL);
|
||||
};
|
||||
|
||||
/* LOCALIZATION ***********************************************/
|
||||
|
||||
abp.localization = abp.localization || {};
|
||||
abp.localization.internal = abp.localization.internal || {};
|
||||
abp.localization.values = abp.localization.values || {};
|
||||
abp.localization.resources = abp.localization.resources || {};
|
||||
|
||||
abp.localization.internal.getResource = function (resourceName) {
|
||||
var resource = abp.localization.resources[resourceName];
|
||||
if (resource) {
|
||||
return resource;
|
||||
}
|
||||
|
||||
var legacySource = abp.localization.values[resourceName];
|
||||
if (legacySource) {
|
||||
return {
|
||||
texts: abp.localization.values[resourceName],
|
||||
baseResources: []
|
||||
};
|
||||
}
|
||||
|
||||
abp.log.warn('Could not find localization source: ' + resourceName);
|
||||
return null;
|
||||
};
|
||||
|
||||
abp.localization.internal.localize = function (key, sourceName) {
|
||||
var resource = abp.localization.internal.getResource(sourceName);
|
||||
if (!resource){
|
||||
return {
|
||||
value: key,
|
||||
found: false
|
||||
};
|
||||
}
|
||||
|
||||
var value = resource.texts[key];
|
||||
if (value === undefined) {
|
||||
for (var i = 0; i < resource.baseResources.length; i++){
|
||||
var basedArguments = Array.prototype.slice.call(arguments, 0);
|
||||
basedArguments[1] = resource.baseResources[i];
|
||||
|
||||
var result = abp.localization.internal.localize.apply(this, basedArguments);
|
||||
if (result.found){
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
value: key,
|
||||
found: false
|
||||
};
|
||||
}
|
||||
|
||||
var copiedArguments = Array.prototype.slice.call(arguments, 0);
|
||||
copiedArguments.splice(1, 1);
|
||||
copiedArguments[0] = value;
|
||||
|
||||
return {
|
||||
value: abp.utils.formatString.apply(this, copiedArguments),
|
||||
found: true
|
||||
};
|
||||
};
|
||||
|
||||
abp.localization.localize = function (key, sourceName) {
|
||||
if (sourceName === '_') { //A convention to suppress the localization
|
||||
return key;
|
||||
}
|
||||
|
||||
if (sourceName) {
|
||||
return abp.localization.internal.localize.apply(this, arguments).value;
|
||||
}
|
||||
|
||||
if (!abp.localization.defaultResourceName) {
|
||||
abp.log.warn('Localization source name is not specified and the defaultResourceName was not defined!');
|
||||
return key;
|
||||
}
|
||||
|
||||
var copiedArguments = Array.prototype.slice.call(arguments, 0);
|
||||
copiedArguments.splice(1, 1, abp.localization.defaultResourceName);
|
||||
|
||||
return abp.localization.internal.localize.apply(this, copiedArguments).value;
|
||||
};
|
||||
|
||||
abp.localization.isLocalized = function (key, sourceName) {
|
||||
if (sourceName === '_') { //A convention to suppress the localization
|
||||
return true;
|
||||
}
|
||||
|
||||
sourceName = sourceName || abp.localization.defaultResourceName;
|
||||
if (!sourceName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return abp.localization.internal.localize(key, sourceName).found;
|
||||
};
|
||||
|
||||
abp.localization.getResource = function (name) {
|
||||
return function () {
|
||||
var copiedArguments = Array.prototype.slice.call(arguments, 0);
|
||||
copiedArguments.splice(1, 0, name);
|
||||
return abp.localization.localize.apply(this, copiedArguments);
|
||||
};
|
||||
};
|
||||
|
||||
abp.localization.defaultResourceName = undefined;
|
||||
abp.localization.currentCulture = {
|
||||
cultureName: undefined
|
||||
};
|
||||
|
||||
var getMapValue = function (packageMaps, packageName, language) {
|
||||
language = language || abp.localization.currentCulture.name;
|
||||
if (!packageMaps || !packageName || !language) {
|
||||
return language;
|
||||
}
|
||||
|
||||
var packageMap = packageMaps[packageName];
|
||||
if (!packageMap) {
|
||||
return language;
|
||||
}
|
||||
|
||||
for (var i = 0; i < packageMap.length; i++) {
|
||||
var map = packageMap[i];
|
||||
if (map.name === language){
|
||||
return map.value;
|
||||
}
|
||||
}
|
||||
|
||||
return language;
|
||||
};
|
||||
|
||||
abp.localization.getLanguagesMap = function (packageName, language) {
|
||||
return getMapValue(abp.localization.languagesMap, packageName, language);
|
||||
};
|
||||
|
||||
abp.localization.getLanguageFilesMap = function (packageName, language) {
|
||||
return getMapValue(abp.localization.languageFilesMap, packageName, language);
|
||||
};
|
||||
|
||||
/* AUTHORIZATION **********************************************/
|
||||
|
||||
abp.auth = abp.auth || {};
|
||||
|
||||
abp.auth.grantedPolicies = abp.auth.grantedPolicies || {};
|
||||
|
||||
abp.auth.isGranted = function (policyName) {
|
||||
return abp.auth.grantedPolicies[policyName] != undefined;
|
||||
};
|
||||
|
||||
abp.auth.isAnyGranted = function () {
|
||||
if (!arguments || arguments.length <= 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
if (abp.auth.isGranted(arguments[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
abp.auth.areAllGranted = function () {
|
||||
if (!arguments || arguments.length <= 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
if (!abp.auth.isGranted(arguments[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
abp.auth.tokenCookieName = 'Abp.AuthToken';
|
||||
|
||||
abp.auth.setToken = function (authToken, expireDate) {
|
||||
abp.utils.setCookieValue(abp.auth.tokenCookieName, authToken, expireDate, abp.appPath, abp.domain);
|
||||
};
|
||||
|
||||
abp.auth.getToken = function () {
|
||||
return abp.utils.getCookieValue(abp.auth.tokenCookieName);
|
||||
}
|
||||
|
||||
abp.auth.clearToken = function () {
|
||||
abp.auth.setToken();
|
||||
}
|
||||
|
||||
/* SETTINGS *************************************************/
|
||||
|
||||
abp.setting = abp.setting || {};
|
||||
|
||||
abp.setting.values = abp.setting.values || {};
|
||||
|
||||
abp.setting.get = function (name) {
|
||||
return abp.setting.values[name];
|
||||
};
|
||||
|
||||
abp.setting.getBoolean = function (name) {
|
||||
var value = abp.setting.get(name);
|
||||
return value == 'true' || value == 'True';
|
||||
};
|
||||
|
||||
abp.setting.getInt = function (name) {
|
||||
return parseInt(abp.setting.values[name]);
|
||||
};
|
||||
|
||||
/* NOTIFICATION *********************************************/
|
||||
//Defines Notification API, not implements it
|
||||
|
||||
abp.notify = abp.notify || {};
|
||||
|
||||
abp.notify.success = function (message, title, options) {
|
||||
abp.log.warn('abp.notify.success is not implemented!');
|
||||
};
|
||||
|
||||
abp.notify.info = function (message, title, options) {
|
||||
abp.log.warn('abp.notify.info is not implemented!');
|
||||
};
|
||||
|
||||
abp.notify.warn = function (message, title, options) {
|
||||
abp.log.warn('abp.notify.warn is not implemented!');
|
||||
};
|
||||
|
||||
abp.notify.error = function (message, title, options) {
|
||||
abp.log.warn('abp.notify.error is not implemented!');
|
||||
};
|
||||
|
||||
/* MESSAGE **************************************************/
|
||||
//Defines Message API, not implements it
|
||||
|
||||
abp.message = abp.message || {};
|
||||
|
||||
abp.message._showMessage = function (message, title) {
|
||||
alert((title || '') + ' ' + message);
|
||||
};
|
||||
|
||||
abp.message.info = function (message, title) {
|
||||
abp.log.warn('abp.message.info is not implemented!');
|
||||
return abp.message._showMessage(message, title);
|
||||
};
|
||||
|
||||
abp.message.success = function (message, title) {
|
||||
abp.log.warn('abp.message.success is not implemented!');
|
||||
return abp.message._showMessage(message, title);
|
||||
};
|
||||
|
||||
abp.message.warn = function (message, title) {
|
||||
abp.log.warn('abp.message.warn is not implemented!');
|
||||
return abp.message._showMessage(message, title);
|
||||
};
|
||||
|
||||
abp.message.error = function (message, title) {
|
||||
abp.log.warn('abp.message.error is not implemented!');
|
||||
return abp.message._showMessage(message, title);
|
||||
};
|
||||
|
||||
abp.message.confirm = function (message, titleOrCallback, callback) {
|
||||
abp.log.warn('abp.message.confirm is not properly implemented!');
|
||||
|
||||
if (titleOrCallback && !(typeof titleOrCallback == 'string')) {
|
||||
callback = titleOrCallback;
|
||||
}
|
||||
|
||||
var result = confirm(message);
|
||||
callback && callback(result);
|
||||
};
|
||||
|
||||
/* UI *******************************************************/
|
||||
|
||||
abp.ui = abp.ui || {};
|
||||
|
||||
/* UI BLOCK */
|
||||
//Defines UI Block API and implements basically
|
||||
|
||||
var $abpBlockArea = document.createElement('div');
|
||||
$abpBlockArea.classList.add('abp-block-area');
|
||||
|
||||
/* opts: { //Can be an object with options or a string for query a selector
|
||||
* elm: a query selector (optional - default: document.body)
|
||||
* busy: boolean (optional - default: false)
|
||||
* promise: A promise with always or finally handler (optional - auto unblocks the ui if provided)
|
||||
* }
|
||||
*/
|
||||
abp.ui.block = function (opts) {
|
||||
if (!opts) {
|
||||
opts = {};
|
||||
} else if (typeof opts == 'string') {
|
||||
opts = {
|
||||
elm: opts
|
||||
};
|
||||
}
|
||||
|
||||
var $elm = document.querySelector(opts.elm) || document.body;
|
||||
|
||||
if (opts.busy) {
|
||||
$abpBlockArea.classList.add('abp-block-area-busy');
|
||||
} else {
|
||||
$abpBlockArea.classList.remove('abp-block-area-busy');
|
||||
}
|
||||
|
||||
if (document.querySelector(opts.elm)) {
|
||||
$abpBlockArea.style.position = 'absolute';
|
||||
} else {
|
||||
$abpBlockArea.style.position = 'fixed';
|
||||
}
|
||||
|
||||
$elm.appendChild($abpBlockArea);
|
||||
|
||||
if (opts.promise) {
|
||||
if (opts.promise.always) { //jQuery.Deferred style
|
||||
opts.promise.always(function () {
|
||||
abp.ui.unblock({
|
||||
$elm: opts.elm
|
||||
});
|
||||
});
|
||||
} else if (opts.promise['finally']) { //Q style
|
||||
opts.promise['finally'](function () {
|
||||
abp.ui.unblock({
|
||||
$elm: opts.elm
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* opts: {
|
||||
*
|
||||
* }
|
||||
*/
|
||||
abp.ui.unblock = function (opts) {
|
||||
var element = document.querySelector('.abp-block-area');
|
||||
if (element) {
|
||||
element.classList.add('abp-block-area-disappearing');
|
||||
setTimeout(function () {
|
||||
if (element) {
|
||||
element.classList.remove('abp-block-area-disappearing');
|
||||
if (element.parentElement) {
|
||||
element.parentElement.removeChild(element);
|
||||
}
|
||||
}
|
||||
}, 250);
|
||||
}
|
||||
};
|
||||
|
||||
/* UI BUSY */
|
||||
//Defines UI Busy API, not implements it
|
||||
|
||||
abp.ui.setBusy = function (opts) {
|
||||
if (!opts) {
|
||||
opts = {
|
||||
busy: true
|
||||
};
|
||||
} else if (typeof opts == 'string') {
|
||||
opts = {
|
||||
elm: opts,
|
||||
busy: true
|
||||
};
|
||||
}
|
||||
|
||||
abp.ui.block(opts);
|
||||
};
|
||||
|
||||
abp.ui.clearBusy = function (opts) {
|
||||
abp.ui.unblock(opts);
|
||||
};
|
||||
|
||||
/* SIMPLE EVENT BUS *****************************************/
|
||||
|
||||
abp.event = (function () {
|
||||
|
||||
var _callbacks = {};
|
||||
|
||||
var on = function (eventName, callback) {
|
||||
if (!_callbacks[eventName]) {
|
||||
_callbacks[eventName] = [];
|
||||
}
|
||||
|
||||
_callbacks[eventName].push(callback);
|
||||
};
|
||||
|
||||
var off = function (eventName, callback) {
|
||||
var callbacks = _callbacks[eventName];
|
||||
if (!callbacks) {
|
||||
return;
|
||||
}
|
||||
|
||||
var index = -1;
|
||||
for (var i = 0; i < callbacks.length; i++) {
|
||||
if (callbacks[i] === callback) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
_callbacks[eventName].splice(index, 1);
|
||||
};
|
||||
|
||||
var trigger = function (eventName) {
|
||||
var callbacks = _callbacks[eventName];
|
||||
if (!callbacks || !callbacks.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
for (var i = 0; i < callbacks.length; i++) {
|
||||
try {
|
||||
callbacks[i].apply(this, args);
|
||||
} catch(e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Public interface ///////////////////////////////////////////////////
|
||||
|
||||
return {
|
||||
on: on,
|
||||
off: off,
|
||||
trigger: trigger
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
/* UTILS ***************************************************/
|
||||
|
||||
abp.utils = abp.utils || {};
|
||||
|
||||
/* Creates a name namespace.
|
||||
* Example:
|
||||
* var taskService = abp.utils.createNamespace(abp, 'services.task');
|
||||
* taskService will be equal to abp.services.task
|
||||
* first argument (root) must be defined first
|
||||
************************************************************/
|
||||
abp.utils.createNamespace = function (root, ns) {
|
||||
var parts = ns.split('.');
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
if (typeof root[parts[i]] == 'undefined') {
|
||||
root[parts[i]] = {};
|
||||
}
|
||||
|
||||
root = root[parts[i]];
|
||||
}
|
||||
|
||||
return root;
|
||||
};
|
||||
|
||||
/* Find and replaces a string (search) to another string (replacement) in
|
||||
* given string (str).
|
||||
* Example:
|
||||
* abp.utils.replaceAll('This is a test string', 'is', 'X') = 'ThX X a test string'
|
||||
************************************************************/
|
||||
abp.utils.replaceAll = function (str, search, replacement) {
|
||||
var fix = search.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||
return str.replace(new RegExp(fix, 'g'), replacement);
|
||||
};
|
||||
|
||||
/* Formats a string just like string.format in C#.
|
||||
* Example:
|
||||
* abp.utils.formatString('Hello {0}','Tuana') = 'Hello Tuana'
|
||||
************************************************************/
|
||||
abp.utils.formatString = function () {
|
||||
if (arguments.length < 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var str = arguments[0];
|
||||
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
var placeHolder = '{' + (i - 1) + '}';
|
||||
str = abp.utils.replaceAll(str, placeHolder, arguments[i]);
|
||||
}
|
||||
|
||||
return str;
|
||||
};
|
||||
|
||||
abp.utils.toPascalCase = function (str) {
|
||||
if (!str || !str.length) {
|
||||
return str;
|
||||
}
|
||||
|
||||
if (str.length === 1) {
|
||||
return str.charAt(0).toUpperCase();
|
||||
}
|
||||
|
||||
return str.charAt(0).toUpperCase() + str.substr(1);
|
||||
}
|
||||
|
||||
abp.utils.toCamelCase = function (str) {
|
||||
if (!str || !str.length) {
|
||||
return str;
|
||||
}
|
||||
|
||||
if (str.length === 1) {
|
||||
return str.charAt(0).toLowerCase();
|
||||
}
|
||||
|
||||
return str.charAt(0).toLowerCase() + str.substr(1);
|
||||
}
|
||||
|
||||
abp.utils.truncateString = function (str, maxLength) {
|
||||
if (!str || !str.length || str.length <= maxLength) {
|
||||
return str;
|
||||
}
|
||||
|
||||
return str.substr(0, maxLength);
|
||||
};
|
||||
|
||||
abp.utils.truncateStringWithPostfix = function (str, maxLength, postfix) {
|
||||
postfix = postfix || '...';
|
||||
|
||||
if (!str || !str.length || str.length <= maxLength) {
|
||||
return str;
|
||||
}
|
||||
|
||||
if (maxLength <= postfix.length) {
|
||||
return postfix.substr(0, maxLength);
|
||||
}
|
||||
|
||||
return str.substr(0, maxLength - postfix.length) + postfix;
|
||||
};
|
||||
|
||||
abp.utils.isFunction = function (obj) {
|
||||
return !!(obj && obj.constructor && obj.call && obj.apply);
|
||||
};
|
||||
|
||||
/**
|
||||
* parameterInfos should be an array of { name, value } objects
|
||||
* where name is query string parameter name and value is it's value.
|
||||
* includeQuestionMark is true by default.
|
||||
*/
|
||||
abp.utils.buildQueryString = function (parameterInfos, includeQuestionMark) {
|
||||
if (includeQuestionMark === undefined) {
|
||||
includeQuestionMark = true;
|
||||
}
|
||||
|
||||
var qs = '';
|
||||
|
||||
function addSeperator() {
|
||||
if (!qs.length) {
|
||||
if (includeQuestionMark) {
|
||||
qs = qs + '?';
|
||||
}
|
||||
} else {
|
||||
qs = qs + '&';
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < parameterInfos.length; ++i) {
|
||||
var parameterInfo = parameterInfos[i];
|
||||
if (parameterInfo.value === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parameterInfo.value === null) {
|
||||
parameterInfo.value = '';
|
||||
}
|
||||
|
||||
addSeperator();
|
||||
|
||||
if (parameterInfo.value.toJSON && typeof parameterInfo.value.toJSON === "function") {
|
||||
qs = qs + parameterInfo.name + '=' + encodeURIComponent(parameterInfo.value.toJSON());
|
||||
} else if (Array.isArray(parameterInfo.value) && parameterInfo.value.length) {
|
||||
for (var j = 0; j < parameterInfo.value.length; j++) {
|
||||
if (j > 0) {
|
||||
addSeperator();
|
||||
}
|
||||
|
||||
qs = qs + parameterInfo.name + '[' + j + ']=' + encodeURIComponent(parameterInfo.value[j]);
|
||||
}
|
||||
} else {
|
||||
qs = qs + parameterInfo.name + '=' + encodeURIComponent(parameterInfo.value);
|
||||
}
|
||||
}
|
||||
|
||||
return qs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a cookie value for given key.
|
||||
* This is a simple implementation created to be used by ABP.
|
||||
* Please use a complete cookie library if you need.
|
||||
* @param {string} key
|
||||
* @param {string} value
|
||||
* @param {Date} expireDate (optional). If not specified the cookie will expire at the end of session.
|
||||
* @param {string} path (optional)
|
||||
*/
|
||||
abp.utils.setCookieValue = function (key, value, expireDate, path) {
|
||||
var cookieValue = encodeURIComponent(key) + '=';
|
||||
|
||||
if (value) {
|
||||
cookieValue = cookieValue + encodeURIComponent(value);
|
||||
}
|
||||
|
||||
if (expireDate) {
|
||||
cookieValue = cookieValue + "; expires=" + expireDate.toUTCString();
|
||||
}
|
||||
|
||||
if (path) {
|
||||
cookieValue = cookieValue + "; path=" + path;
|
||||
}
|
||||
|
||||
document.cookie = cookieValue;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets a cookie with given key.
|
||||
* This is a simple implementation created to be used by ABP.
|
||||
* Please use a complete cookie library if you need.
|
||||
* @param {string} key
|
||||
* @returns {string} Cookie value or null
|
||||
*/
|
||||
abp.utils.getCookieValue = function (key) {
|
||||
var equalities = document.cookie.split('; ');
|
||||
for (var i = 0; i < equalities.length; i++) {
|
||||
if (!equalities[i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var splitted = equalities[i].split('=');
|
||||
if (splitted.length != 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (decodeURIComponent(splitted[0]) === key) {
|
||||
return decodeURIComponent(splitted[1] || '');
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes cookie for given key.
|
||||
* This is a simple implementation created to be used by ABP.
|
||||
* Please use a complete cookie library if you need.
|
||||
* @param {string} key
|
||||
* @param {string} path (optional)
|
||||
*/
|
||||
abp.utils.deleteCookie = function (key, path) {
|
||||
var cookieValue = encodeURIComponent(key) + '=';
|
||||
|
||||
cookieValue = cookieValue + "; expires=" + (new Date(new Date().getTime() - 86400000)).toUTCString();
|
||||
|
||||
if (path) {
|
||||
cookieValue = cookieValue + "; path=" + path;
|
||||
}
|
||||
|
||||
document.cookie = cookieValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape HTML to help prevent XSS attacks.
|
||||
*/
|
||||
abp.utils.htmlEscape = function (html) {
|
||||
return typeof html === 'string' ? html.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"') : html;
|
||||
}
|
||||
|
||||
/* SECURITY ***************************************/
|
||||
abp.security = abp.security || {};
|
||||
abp.security.antiForgery = abp.security.antiForgery || {};
|
||||
|
||||
abp.security.antiForgery.tokenCookieName = 'XSRF-TOKEN';
|
||||
abp.security.antiForgery.tokenHeaderName = 'RequestVerificationToken';
|
||||
|
||||
abp.security.antiForgery.getToken = function () {
|
||||
return abp.utils.getCookieValue(abp.security.antiForgery.tokenCookieName);
|
||||
};
|
||||
|
||||
/* CLOCK *****************************************/
|
||||
abp.clock = abp.clock || {};
|
||||
|
||||
abp.clock.kind = 'Unspecified';
|
||||
|
||||
abp.clock.supportsMultipleTimezone = function () {
|
||||
return abp.clock.kind === 'Utc';
|
||||
};
|
||||
|
||||
var toLocal = function (date) {
|
||||
return new Date(
|
||||
date.getFullYear(),
|
||||
date.getMonth(),
|
||||
date.getDate(),
|
||||
date.getHours(),
|
||||
date.getMinutes(),
|
||||
date.getSeconds(),
|
||||
date.getMilliseconds()
|
||||
);
|
||||
};
|
||||
|
||||
var toUtc = function (date) {
|
||||
return Date.UTC(
|
||||
date.getUTCFullYear(),
|
||||
date.getUTCMonth(),
|
||||
date.getUTCDate(),
|
||||
date.getUTCHours(),
|
||||
date.getUTCMinutes(),
|
||||
date.getUTCSeconds(),
|
||||
date.getUTCMilliseconds()
|
||||
);
|
||||
};
|
||||
|
||||
abp.clock.now = function () {
|
||||
if (abp.clock.kind === 'Utc') {
|
||||
return toUtc(new Date());
|
||||
}
|
||||
return new Date();
|
||||
};
|
||||
|
||||
abp.clock.normalize = function (date) {
|
||||
var kind = abp.clock.kind;
|
||||
|
||||
if (kind === 'Unspecified') {
|
||||
return date;
|
||||
}
|
||||
|
||||
if (kind === 'Local') {
|
||||
return toLocal(date);
|
||||
}
|
||||
|
||||
if (kind === 'Utc') {
|
||||
return toUtc(date);
|
||||
}
|
||||
};
|
||||
|
||||
/* FEATURES *************************************************/
|
||||
|
||||
abp.features = abp.features || {};
|
||||
|
||||
abp.features.values = abp.features.values || {};
|
||||
|
||||
abp.features.isEnabled = function(name){
|
||||
var value = abp.features.get(name);
|
||||
return value == 'true' || value == 'True';
|
||||
}
|
||||
|
||||
abp.features.get = function (name) {
|
||||
return abp.features.values[name];
|
||||
};
|
||||
|
||||
/* GLOBAL FEATURES *************************************************/
|
||||
|
||||
abp.globalFeatures = abp.globalFeatures || {};
|
||||
|
||||
abp.globalFeatures.enabledFeatures = abp.globalFeatures.enabledFeatures || [];
|
||||
|
||||
abp.globalFeatures.isEnabled = function(name){
|
||||
return abp.globalFeatures.enabledFeatures.indexOf(name) != -1;
|
||||
}
|
||||
|
||||
})();
|
411
aspnet-core/src/HospitalManagementSystem.HttpApi.Host/wwwroot/libs/abp/jquery/abp.jquery.js
vendored
Normal file
411
aspnet-core/src/HospitalManagementSystem.HttpApi.Host/wwwroot/libs/abp/jquery/abp.jquery.js
vendored
Normal file
@ -0,0 +1,411 @@
|
||||
var abp = abp || {};
|
||||
(function($) {
|
||||
|
||||
if (!$) {
|
||||
throw "abp/jquery library requires the jquery library included to the page!";
|
||||
}
|
||||
|
||||
// ABP CORE OVERRIDES /////////////////////////////////////////////////////
|
||||
|
||||
abp.message._showMessage = function (message, title) {
|
||||
alert((title || '') + ' ' + message);
|
||||
|
||||
return $.Deferred(function ($dfd) {
|
||||
$dfd.resolve();
|
||||
});
|
||||
};
|
||||
|
||||
abp.message.confirm = function (message, titleOrCallback, callback) {
|
||||
if (titleOrCallback && !(typeof titleOrCallback == 'string')) {
|
||||
callback = titleOrCallback;
|
||||
}
|
||||
|
||||
var result = confirm(message);
|
||||
callback && callback(result);
|
||||
|
||||
return $.Deferred(function ($dfd) {
|
||||
$dfd.resolve(result);
|
||||
});
|
||||
};
|
||||
|
||||
abp.utils.isFunction = function (obj) {
|
||||
return $.isFunction(obj);
|
||||
};
|
||||
|
||||
// JQUERY EXTENSIONS //////////////////////////////////////////////////////
|
||||
|
||||
$.fn.findWithSelf = function (selector) {
|
||||
return this.filter(selector).add(this.find(selector));
|
||||
};
|
||||
|
||||
// DOM ////////////////////////////////////////////////////////////////////
|
||||
|
||||
abp.dom = abp.dom || {};
|
||||
|
||||
abp.dom.onNodeAdded = function (callback) {
|
||||
abp.event.on('abp.dom.nodeAdded', callback);
|
||||
};
|
||||
|
||||
abp.dom.onNodeRemoved = function (callback) {
|
||||
abp.event.on('abp.dom.nodeRemoved', callback);
|
||||
};
|
||||
|
||||
var mutationObserverCallback = function (mutationsList) {
|
||||
for (var i = 0; i < mutationsList.length; i++) {
|
||||
var mutation = mutationsList[i];
|
||||
if (mutation.type === 'childList') {
|
||||
if (mutation.addedNodes && mutation.removedNodes.length) {
|
||||
for (var k = 0; k < mutation.removedNodes.length; k++) {
|
||||
abp.event.trigger(
|
||||
'abp.dom.nodeRemoved',
|
||||
{
|
||||
$el: $(mutation.removedNodes[k])
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (mutation.addedNodes && mutation.addedNodes.length) {
|
||||
for (var j = 0; j < mutation.addedNodes.length; j++) {
|
||||
abp.event.trigger(
|
||||
'abp.dom.nodeAdded',
|
||||
{
|
||||
$el: $(mutation.addedNodes[j])
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$(function(){
|
||||
new MutationObserver(mutationObserverCallback).observe(
|
||||
$('body')[0],
|
||||
{
|
||||
subtree: true,
|
||||
childList: true
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// AJAX ///////////////////////////////////////////////////////////////////
|
||||
|
||||
abp.ajax = function (userOptions) {
|
||||
userOptions = userOptions || {};
|
||||
|
||||
var options = $.extend(true, {}, abp.ajax.defaultOpts, userOptions);
|
||||
|
||||
options.success = undefined;
|
||||
options.error = undefined;
|
||||
|
||||
var xhr = null;
|
||||
var promise = $.Deferred(function ($dfd) {
|
||||
xhr = $.ajax(options)
|
||||
.done(function (data, textStatus, jqXHR) {
|
||||
$dfd.resolve(data);
|
||||
userOptions.success && userOptions.success(data);
|
||||
}).fail(function (jqXHR) {
|
||||
if(jqXHR.statusText === 'abort') {
|
||||
//ajax request is abort, ignore error handle.
|
||||
return;
|
||||
}
|
||||
if (jqXHR.getResponseHeader('_AbpErrorFormat') === 'true') {
|
||||
abp.ajax.handleAbpErrorResponse(jqXHR, userOptions, $dfd);
|
||||
} else {
|
||||
abp.ajax.handleNonAbpErrorResponse(jqXHR, userOptions, $dfd);
|
||||
}
|
||||
});
|
||||
}).promise();
|
||||
|
||||
promise['jqXHR'] = xhr;
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
$.extend(abp.ajax, {
|
||||
defaultOpts: {
|
||||
dataType: 'json',
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
headers: {
|
||||
'X-Requested-With': 'XMLHttpRequest'
|
||||
}
|
||||
},
|
||||
|
||||
defaultError: {
|
||||
message: 'An error has occurred!',
|
||||
details: 'Error detail not sent by server.'
|
||||
},
|
||||
|
||||
defaultError401: {
|
||||
message: 'You are not authenticated!',
|
||||
details: 'You should be authenticated (sign in) in order to perform this operation.'
|
||||
},
|
||||
|
||||
defaultError403: {
|
||||
message: 'You are not authorized!',
|
||||
details: 'You are not allowed to perform this operation.'
|
||||
},
|
||||
|
||||
defaultError404: {
|
||||
message: 'Resource not found!',
|
||||
details: 'The resource requested could not found on the server.'
|
||||
},
|
||||
|
||||
logError: function (error) {
|
||||
abp.log.error(error);
|
||||
},
|
||||
|
||||
showError: function (error) {
|
||||
if (error.details) {
|
||||
return abp.message.error(error.details, error.message);
|
||||
} else {
|
||||
return abp.message.error(error.message || abp.ajax.defaultError.message);
|
||||
}
|
||||
},
|
||||
|
||||
handleTargetUrl: function (targetUrl) {
|
||||
if (!targetUrl) {
|
||||
location.href = abp.appPath;
|
||||
} else {
|
||||
location.href = targetUrl;
|
||||
}
|
||||
},
|
||||
|
||||
handleErrorStatusCode: function (status) {
|
||||
switch (status) {
|
||||
case 401:
|
||||
abp.ajax.handleUnAuthorizedRequest(
|
||||
abp.ajax.showError(abp.ajax.defaultError401),
|
||||
abp.appPath
|
||||
);
|
||||
break;
|
||||
case 403:
|
||||
abp.ajax.showError(abp.ajax.defaultError403);
|
||||
break;
|
||||
case 404:
|
||||
abp.ajax.showError(abp.ajax.defaultError404);
|
||||
break;
|
||||
default:
|
||||
abp.ajax.showError(abp.ajax.defaultError);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
handleNonAbpErrorResponse: function (jqXHR, userOptions, $dfd) {
|
||||
if (userOptions.abpHandleError !== false) {
|
||||
abp.ajax.handleErrorStatusCode(jqXHR.status);
|
||||
}
|
||||
|
||||
$dfd.reject.apply(this, arguments);
|
||||
userOptions.error && userOptions.error.apply(this, arguments);
|
||||
},
|
||||
|
||||
handleAbpErrorResponse: function (jqXHR, userOptions, $dfd) {
|
||||
var messagePromise = null;
|
||||
|
||||
var responseJSON = jqXHR.responseJSON ? jqXHR.responseJSON : JSON.parse(jqXHR.responseText);
|
||||
|
||||
if (userOptions.abpHandleError !== false) {
|
||||
messagePromise = abp.ajax.showError(responseJSON.error);
|
||||
}
|
||||
|
||||
abp.ajax.logError(responseJSON.error);
|
||||
|
||||
$dfd && $dfd.reject(responseJSON.error, jqXHR);
|
||||
userOptions.error && userOptions.error(responseJSON.error, jqXHR);
|
||||
|
||||
if (jqXHR.status === 401 && userOptions.abpHandleError !== false) {
|
||||
abp.ajax.handleUnAuthorizedRequest(messagePromise);
|
||||
}
|
||||
},
|
||||
|
||||
handleUnAuthorizedRequest: function (messagePromise, targetUrl) {
|
||||
if (messagePromise) {
|
||||
messagePromise.done(function () {
|
||||
abp.ajax.handleTargetUrl(targetUrl);
|
||||
});
|
||||
} else {
|
||||
abp.ajax.handleTargetUrl(targetUrl);
|
||||
}
|
||||
},
|
||||
|
||||
blockUI: function (options) {
|
||||
if (options.blockUI) {
|
||||
if (options.blockUI === true) { //block whole page
|
||||
abp.ui.setBusy();
|
||||
} else { //block an element
|
||||
abp.ui.setBusy(options.blockUI);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
unblockUI: function (options) {
|
||||
if (options.blockUI) {
|
||||
if (options.blockUI === true) { //unblock whole page
|
||||
abp.ui.clearBusy();
|
||||
} else { //unblock an element
|
||||
abp.ui.clearBusy(options.blockUI);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
ajaxSendHandler: function (event, request, settings) {
|
||||
var token = abp.security.antiForgery.getToken();
|
||||
if (!token) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!settings.headers || settings.headers[abp.security.antiForgery.tokenHeaderName] === undefined) {
|
||||
request.setRequestHeader(abp.security.antiForgery.tokenHeaderName, token);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$(document).ajaxSend(function (event, request, settings) {
|
||||
return abp.ajax.ajaxSendHandler(event, request, settings);
|
||||
});
|
||||
|
||||
abp.event.on('abp.configurationInitialized', function () {
|
||||
var l = abp.localization.getResource('AbpUi');
|
||||
|
||||
abp.ajax.defaultError.message = l('DefaultErrorMessage');
|
||||
abp.ajax.defaultError.details = l('DefaultErrorMessageDetail');
|
||||
abp.ajax.defaultError401.message = l('DefaultErrorMessage401');
|
||||
abp.ajax.defaultError401.details = l('DefaultErrorMessage401Detail');
|
||||
abp.ajax.defaultError403.message = l('DefaultErrorMessage403');
|
||||
abp.ajax.defaultError403.details = l('DefaultErrorMessage403Detail');
|
||||
abp.ajax.defaultError404.message = l('DefaultErrorMessage404');
|
||||
abp.ajax.defaultError404.details = l('DefaultErrorMessage404Detail');
|
||||
});
|
||||
|
||||
// RESOURCE LOADER ////////////////////////////////////////////////////////
|
||||
|
||||
/* UrlStates enum */
|
||||
var UrlStates = {
|
||||
LOADING: 'LOADING',
|
||||
LOADED: 'LOADED',
|
||||
FAILED: 'FAILED'
|
||||
};
|
||||
|
||||
/* UrlInfo class */
|
||||
function UrlInfo(url) {
|
||||
this.url = url;
|
||||
this.state = UrlStates.LOADING;
|
||||
this.loadCallbacks = [];
|
||||
this.failCallbacks = [];
|
||||
}
|
||||
|
||||
UrlInfo.prototype.succeed = function () {
|
||||
this.state = UrlStates.LOADED;
|
||||
for (var i = 0; i < this.loadCallbacks.length; i++) {
|
||||
this.loadCallbacks[i]();
|
||||
}
|
||||
};
|
||||
|
||||
UrlInfo.prototype.failed = function () {
|
||||
this.state = UrlStates.FAILED;
|
||||
for (var i = 0; i < this.failCallbacks.length; i++) {
|
||||
this.failCallbacks[i]();
|
||||
}
|
||||
};
|
||||
|
||||
UrlInfo.prototype.handleCallbacks = function (loadCallback, failCallback) {
|
||||
switch (this.state) {
|
||||
case UrlStates.LOADED:
|
||||
loadCallback && loadCallback();
|
||||
break;
|
||||
case UrlStates.FAILED:
|
||||
failCallback && failCallback();
|
||||
break;
|
||||
case UrlStates.LOADING:
|
||||
this.addCallbacks(loadCallback, failCallback);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
UrlInfo.prototype.addCallbacks = function (loadCallback, failCallback) {
|
||||
loadCallback && this.loadCallbacks.push(loadCallback);
|
||||
failCallback && this.failCallbacks.push(failCallback);
|
||||
};
|
||||
|
||||
/* ResourceLoader API */
|
||||
|
||||
abp.ResourceLoader = (function () {
|
||||
|
||||
var _urlInfos = {};
|
||||
|
||||
function getCacheKey(url) {
|
||||
return url;
|
||||
}
|
||||
|
||||
function appendTimeToUrl(url) {
|
||||
|
||||
if (url.indexOf('?') < 0) {
|
||||
url += '?';
|
||||
} else {
|
||||
url += '&';
|
||||
}
|
||||
|
||||
url += '_=' + new Date().getTime();
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
var _loadFromUrl = function (url, loadCallback, failCallback, serverLoader) {
|
||||
|
||||
var cacheKey = getCacheKey(url);
|
||||
|
||||
var urlInfo = _urlInfos[cacheKey];
|
||||
|
||||
if (urlInfo) {
|
||||
urlInfo.handleCallbacks(loadCallback, failCallback);
|
||||
return;
|
||||
}
|
||||
|
||||
_urlInfos[cacheKey] = urlInfo = new UrlInfo(url);
|
||||
urlInfo.addCallbacks(loadCallback, failCallback);
|
||||
|
||||
serverLoader(urlInfo);
|
||||
};
|
||||
|
||||
var _loadScript = function (url, loadCallback, failCallback) {
|
||||
var nonce = document.body.nonce || document.body.getAttribute('nonce');
|
||||
_loadFromUrl(url, loadCallback, failCallback, function (urlInfo) {
|
||||
$.get({
|
||||
url: url,
|
||||
dataType: 'text'
|
||||
})
|
||||
.done(function (script) {
|
||||
if(nonce){
|
||||
$.globalEval(script, { nonce: nonce});
|
||||
}else{
|
||||
$.globalEval(script);
|
||||
}
|
||||
urlInfo.succeed();
|
||||
})
|
||||
.fail(function () {
|
||||
urlInfo.failed();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var _loadStyle = function (url) {
|
||||
_loadFromUrl(url, undefined, undefined, function (urlInfo) {
|
||||
|
||||
$('<link/>', {
|
||||
rel: 'stylesheet',
|
||||
type: 'text/css',
|
||||
href: appendTimeToUrl(url)
|
||||
}).appendTo('head');
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
loadScript: _loadScript,
|
||||
loadStyle: _loadStyle
|
||||
}
|
||||
})();
|
||||
|
||||
})(jQuery);
|
46
aspnet-core/src/HospitalManagementSystem.HttpApi.Host/wwwroot/libs/abp/luxon/abp.luxon.js
vendored
Normal file
46
aspnet-core/src/HospitalManagementSystem.HttpApi.Host/wwwroot/libs/abp/luxon/abp.luxon.js
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
var abp = abp || {};
|
||||
(function () {
|
||||
|
||||
if (!luxon) {
|
||||
throw "abp/luxon library requires the luxon library included to the page!";
|
||||
}
|
||||
|
||||
/* TIMING *************************************************/
|
||||
|
||||
abp.timing = abp.timing || {};
|
||||
|
||||
var setObjectValue = function (obj, property, value) {
|
||||
if (typeof property === "string") {
|
||||
property = property.split('.');
|
||||
}
|
||||
|
||||
if (property.length > 1) {
|
||||
var p = property.shift();
|
||||
setObjectValue(obj[p], property, value);
|
||||
} else {
|
||||
obj[property[0]] = value;
|
||||
}
|
||||
}
|
||||
|
||||
var getObjectValue = function (obj, property) {
|
||||
return property.split('.').reduce((a, v) => a[v], obj)
|
||||
}
|
||||
|
||||
abp.timing.convertFieldsToIsoDate = function (form, fields) {
|
||||
for (var field of fields) {
|
||||
var dateTime = luxon.DateTime
|
||||
.fromFormat(
|
||||
getObjectValue(form, field),
|
||||
abp.localization.currentCulture.dateTimeFormat.shortDatePattern,
|
||||
{locale: abp.localization.currentCulture.cultureName}
|
||||
);
|
||||
|
||||
if (!dateTime.invalid) {
|
||||
setObjectValue(form, field, dateTime.toFormat("yyyy-MM-dd HH:mm:ss"))
|
||||
}
|
||||
}
|
||||
|
||||
return form;
|
||||
}
|
||||
|
||||
})(jQuery);
|
694
aspnet-core/src/HospitalManagementSystem.HttpApi.Host/wwwroot/libs/abp/utils/abp-utils.umd.js
vendored
Normal file
694
aspnet-core/src/HospitalManagementSystem.HttpApi.Host/wwwroot/libs/abp/utils/abp-utils.umd.js
vendored
Normal file
@ -0,0 +1,694 @@
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('just-compare')) :
|
||||
typeof define === 'function' && define.amd ? define('@abp/utils', ['exports', 'just-compare'], factory) :
|
||||
(global = global || self, factory((global.abp = global.abp || {}, global.abp.utils = global.abp.utils || {}, global.abp.utils.common = {}), global.compare));
|
||||
}(this, (function (exports, compare) { 'use strict';
|
||||
|
||||
compare = compare && Object.prototype.hasOwnProperty.call(compare, 'default') ? compare['default'] : compare;
|
||||
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
***************************************************************************** */
|
||||
/* global Reflect, Promise */
|
||||
var extendStatics = function (d, b) {
|
||||
extendStatics = Object.setPrototypeOf ||
|
||||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||
function (d, b) { for (var p in b)
|
||||
if (b.hasOwnProperty(p))
|
||||
d[p] = b[p]; };
|
||||
return extendStatics(d, b);
|
||||
};
|
||||
function __extends(d, b) {
|
||||
extendStatics(d, b);
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
}
|
||||
var __assign = function () {
|
||||
__assign = Object.assign || function __assign(t) {
|
||||
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
||||
s = arguments[i];
|
||||
for (var p in s)
|
||||
if (Object.prototype.hasOwnProperty.call(s, p))
|
||||
t[p] = s[p];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
return __assign.apply(this, arguments);
|
||||
};
|
||||
function __rest(s, e) {
|
||||
var t = {};
|
||||
for (var p in s)
|
||||
if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
||||
t[p] = s[p];
|
||||
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
||||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
||||
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
||||
t[p[i]] = s[p[i]];
|
||||
}
|
||||
return t;
|
||||
}
|
||||
function __decorate(decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
||||
r = Reflect.decorate(decorators, target, key, desc);
|
||||
else
|
||||
for (var i = decorators.length - 1; i >= 0; i--)
|
||||
if (d = decorators[i])
|
||||
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
}
|
||||
function __param(paramIndex, decorator) {
|
||||
return function (target, key) { decorator(target, key, paramIndex); };
|
||||
}
|
||||
function __metadata(metadataKey, metadataValue) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function")
|
||||
return Reflect.metadata(metadataKey, metadataValue);
|
||||
}
|
||||
function __awaiter(thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try {
|
||||
step(generator.next(value));
|
||||
}
|
||||
catch (e) {
|
||||
reject(e);
|
||||
} }
|
||||
function rejected(value) { try {
|
||||
step(generator["throw"](value));
|
||||
}
|
||||
catch (e) {
|
||||
reject(e);
|
||||
} }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
}
|
||||
function __generator(thisArg, body) {
|
||||
var _ = { label: 0, sent: function () { if (t[0] & 1)
|
||||
throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
||||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g;
|
||||
function verb(n) { return function (v) { return step([n, v]); }; }
|
||||
function step(op) {
|
||||
if (f)
|
||||
throw new TypeError("Generator is already executing.");
|
||||
while (_)
|
||||
try {
|
||||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done)
|
||||
return t;
|
||||
if (y = 0, t)
|
||||
op = [op[0] & 2, t.value];
|
||||
switch (op[0]) {
|
||||
case 0:
|
||||
case 1:
|
||||
t = op;
|
||||
break;
|
||||
case 4:
|
||||
_.label++;
|
||||
return { value: op[1], done: false };
|
||||
case 5:
|
||||
_.label++;
|
||||
y = op[1];
|
||||
op = [0];
|
||||
continue;
|
||||
case 7:
|
||||
op = _.ops.pop();
|
||||
_.trys.pop();
|
||||
continue;
|
||||
default:
|
||||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
|
||||
_ = 0;
|
||||
continue;
|
||||
}
|
||||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) {
|
||||
_.label = op[1];
|
||||
break;
|
||||
}
|
||||
if (op[0] === 6 && _.label < t[1]) {
|
||||
_.label = t[1];
|
||||
t = op;
|
||||
break;
|
||||
}
|
||||
if (t && _.label < t[2]) {
|
||||
_.label = t[2];
|
||||
_.ops.push(op);
|
||||
break;
|
||||
}
|
||||
if (t[2])
|
||||
_.ops.pop();
|
||||
_.trys.pop();
|
||||
continue;
|
||||
}
|
||||
op = body.call(thisArg, _);
|
||||
}
|
||||
catch (e) {
|
||||
op = [6, e];
|
||||
y = 0;
|
||||
}
|
||||
finally {
|
||||
f = t = 0;
|
||||
}
|
||||
if (op[0] & 5)
|
||||
throw op[1];
|
||||
return { value: op[0] ? op[1] : void 0, done: true };
|
||||
}
|
||||
}
|
||||
var __createBinding = Object.create ? (function (o, m, k, k2) {
|
||||
if (k2 === undefined)
|
||||
k2 = k;
|
||||
Object.defineProperty(o, k2, { enumerable: true, get: function () { return m[k]; } });
|
||||
}) : (function (o, m, k, k2) {
|
||||
if (k2 === undefined)
|
||||
k2 = k;
|
||||
o[k2] = m[k];
|
||||
});
|
||||
function __exportStar(m, exports) {
|
||||
for (var p in m)
|
||||
if (p !== "default" && !exports.hasOwnProperty(p))
|
||||
__createBinding(exports, m, p);
|
||||
}
|
||||
function __values(o) {
|
||||
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
||||
if (m)
|
||||
return m.call(o);
|
||||
if (o && typeof o.length === "number")
|
||||
return {
|
||||
next: function () {
|
||||
if (o && i >= o.length)
|
||||
o = void 0;
|
||||
return { value: o && o[i++], done: !o };
|
||||
}
|
||||
};
|
||||
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
||||
}
|
||||
function __read(o, n) {
|
||||
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
||||
if (!m)
|
||||
return o;
|
||||
var i = m.call(o), r, ar = [], e;
|
||||
try {
|
||||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done)
|
||||
ar.push(r.value);
|
||||
}
|
||||
catch (error) {
|
||||
e = { error: error };
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
if (r && !r.done && (m = i["return"]))
|
||||
m.call(i);
|
||||
}
|
||||
finally {
|
||||
if (e)
|
||||
throw e.error;
|
||||
}
|
||||
}
|
||||
return ar;
|
||||
}
|
||||
function __spread() {
|
||||
for (var ar = [], i = 0; i < arguments.length; i++)
|
||||
ar = ar.concat(__read(arguments[i]));
|
||||
return ar;
|
||||
}
|
||||
function __spreadArrays() {
|
||||
for (var s = 0, i = 0, il = arguments.length; i < il; i++)
|
||||
s += arguments[i].length;
|
||||
for (var r = Array(s), k = 0, i = 0; i < il; i++)
|
||||
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
|
||||
r[k] = a[j];
|
||||
return r;
|
||||
}
|
||||
;
|
||||
function __await(v) {
|
||||
return this instanceof __await ? (this.v = v, this) : new __await(v);
|
||||
}
|
||||
function __asyncGenerator(thisArg, _arguments, generator) {
|
||||
if (!Symbol.asyncIterator)
|
||||
throw new TypeError("Symbol.asyncIterator is not defined.");
|
||||
var g = generator.apply(thisArg, _arguments || []), i, q = [];
|
||||
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
|
||||
function verb(n) { if (g[n])
|
||||
i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
|
||||
function resume(n, v) { try {
|
||||
step(g[n](v));
|
||||
}
|
||||
catch (e) {
|
||||
settle(q[0][3], e);
|
||||
} }
|
||||
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
|
||||
function fulfill(value) { resume("next", value); }
|
||||
function reject(value) { resume("throw", value); }
|
||||
function settle(f, v) { if (f(v), q.shift(), q.length)
|
||||
resume(q[0][0], q[0][1]); }
|
||||
}
|
||||
function __asyncDelegator(o) {
|
||||
var i, p;
|
||||
return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
|
||||
function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
|
||||
}
|
||||
function __asyncValues(o) {
|
||||
if (!Symbol.asyncIterator)
|
||||
throw new TypeError("Symbol.asyncIterator is not defined.");
|
||||
var m = o[Symbol.asyncIterator], i;
|
||||
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
||||
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
||||
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function (v) { resolve({ value: v, done: d }); }, reject); }
|
||||
}
|
||||
function __makeTemplateObject(cooked, raw) {
|
||||
if (Object.defineProperty) {
|
||||
Object.defineProperty(cooked, "raw", { value: raw });
|
||||
}
|
||||
else {
|
||||
cooked.raw = raw;
|
||||
}
|
||||
return cooked;
|
||||
}
|
||||
;
|
||||
var __setModuleDefault = Object.create ? (function (o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function (o, v) {
|
||||
o["default"] = v;
|
||||
};
|
||||
function __importStar(mod) {
|
||||
if (mod && mod.__esModule)
|
||||
return mod;
|
||||
var result = {};
|
||||
if (mod != null)
|
||||
for (var k in mod)
|
||||
if (Object.hasOwnProperty.call(mod, k))
|
||||
__createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
}
|
||||
function __importDefault(mod) {
|
||||
return (mod && mod.__esModule) ? mod : { default: mod };
|
||||
}
|
||||
function __classPrivateFieldGet(receiver, privateMap) {
|
||||
if (!privateMap.has(receiver)) {
|
||||
throw new TypeError("attempted to get private field on non-instance");
|
||||
}
|
||||
return privateMap.get(receiver);
|
||||
}
|
||||
function __classPrivateFieldSet(receiver, privateMap, value) {
|
||||
if (!privateMap.has(receiver)) {
|
||||
throw new TypeError("attempted to set private field on non-instance");
|
||||
}
|
||||
privateMap.set(receiver, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
var ListNode = /** @class */ (function () {
|
||||
function ListNode(value) {
|
||||
this.value = value;
|
||||
}
|
||||
return ListNode;
|
||||
}());
|
||||
var LinkedList = /** @class */ (function () {
|
||||
function LinkedList() {
|
||||
this.size = 0;
|
||||
}
|
||||
Object.defineProperty(LinkedList.prototype, "head", {
|
||||
get: function () {
|
||||
return this.first;
|
||||
},
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(LinkedList.prototype, "tail", {
|
||||
get: function () {
|
||||
return this.last;
|
||||
},
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(LinkedList.prototype, "length", {
|
||||
get: function () {
|
||||
return this.size;
|
||||
},
|
||||
enumerable: false,
|
||||
configurable: true
|
||||
});
|
||||
LinkedList.prototype.attach = function (value, previousNode, nextNode) {
|
||||
if (!previousNode)
|
||||
return this.addHead(value);
|
||||
if (!nextNode)
|
||||
return this.addTail(value);
|
||||
var node = new ListNode(value);
|
||||
node.previous = previousNode;
|
||||
previousNode.next = node;
|
||||
node.next = nextNode;
|
||||
nextNode.previous = node;
|
||||
this.size++;
|
||||
return node;
|
||||
};
|
||||
LinkedList.prototype.attachMany = function (values, previousNode, nextNode) {
|
||||
if (!values.length)
|
||||
return [];
|
||||
if (!previousNode)
|
||||
return this.addManyHead(values);
|
||||
if (!nextNode)
|
||||
return this.addManyTail(values);
|
||||
var list = new LinkedList();
|
||||
list.addManyTail(values);
|
||||
list.first.previous = previousNode;
|
||||
previousNode.next = list.first;
|
||||
list.last.next = nextNode;
|
||||
nextNode.previous = list.last;
|
||||
this.size += values.length;
|
||||
return list.toNodeArray();
|
||||
};
|
||||
LinkedList.prototype.detach = function (node) {
|
||||
if (!node.previous)
|
||||
return this.dropHead();
|
||||
if (!node.next)
|
||||
return this.dropTail();
|
||||
node.previous.next = node.next;
|
||||
node.next.previous = node.previous;
|
||||
this.size--;
|
||||
return node;
|
||||
};
|
||||
LinkedList.prototype.add = function (value) {
|
||||
var _this = this;
|
||||
return {
|
||||
after: function () {
|
||||
var _a;
|
||||
var params = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
params[_i] = arguments[_i];
|
||||
}
|
||||
return (_a = _this.addAfter).call.apply(_a, __spread([_this, value], params));
|
||||
},
|
||||
before: function () {
|
||||
var _a;
|
||||
var params = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
params[_i] = arguments[_i];
|
||||
}
|
||||
return (_a = _this.addBefore).call.apply(_a, __spread([_this, value], params));
|
||||
},
|
||||
byIndex: function (position) { return _this.addByIndex(value, position); },
|
||||
head: function () { return _this.addHead(value); },
|
||||
tail: function () { return _this.addTail(value); },
|
||||
};
|
||||
};
|
||||
LinkedList.prototype.addMany = function (values) {
|
||||
var _this = this;
|
||||
return {
|
||||
after: function () {
|
||||
var _a;
|
||||
var params = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
params[_i] = arguments[_i];
|
||||
}
|
||||
return (_a = _this.addManyAfter).call.apply(_a, __spread([_this, values], params));
|
||||
},
|
||||
before: function () {
|
||||
var _a;
|
||||
var params = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
params[_i] = arguments[_i];
|
||||
}
|
||||
return (_a = _this.addManyBefore).call.apply(_a, __spread([_this, values], params));
|
||||
},
|
||||
byIndex: function (position) { return _this.addManyByIndex(values, position); },
|
||||
head: function () { return _this.addManyHead(values); },
|
||||
tail: function () { return _this.addManyTail(values); },
|
||||
};
|
||||
};
|
||||
LinkedList.prototype.addAfter = function (value, previousValue, compareFn) {
|
||||
if (compareFn === void 0) { compareFn = compare; }
|
||||
var previous = this.find(function (node) { return compareFn(node.value, previousValue); });
|
||||
return previous ? this.attach(value, previous, previous.next) : this.addTail(value);
|
||||
};
|
||||
LinkedList.prototype.addBefore = function (value, nextValue, compareFn) {
|
||||
if (compareFn === void 0) { compareFn = compare; }
|
||||
var next = this.find(function (node) { return compareFn(node.value, nextValue); });
|
||||
return next ? this.attach(value, next.previous, next) : this.addHead(value);
|
||||
};
|
||||
LinkedList.prototype.addByIndex = function (value, position) {
|
||||
if (position < 0)
|
||||
position += this.size;
|
||||
else if (position >= this.size)
|
||||
return this.addTail(value);
|
||||
if (position <= 0)
|
||||
return this.addHead(value);
|
||||
var next = this.get(position);
|
||||
return this.attach(value, next.previous, next);
|
||||
};
|
||||
LinkedList.prototype.addHead = function (value) {
|
||||
var node = new ListNode(value);
|
||||
node.next = this.first;
|
||||
if (this.first)
|
||||
this.first.previous = node;
|
||||
else
|
||||
this.last = node;
|
||||
this.first = node;
|
||||
this.size++;
|
||||
return node;
|
||||
};
|
||||
LinkedList.prototype.addTail = function (value) {
|
||||
var node = new ListNode(value);
|
||||
if (this.first) {
|
||||
node.previous = this.last;
|
||||
this.last.next = node;
|
||||
this.last = node;
|
||||
}
|
||||
else {
|
||||
this.first = node;
|
||||
this.last = node;
|
||||
}
|
||||
this.size++;
|
||||
return node;
|
||||
};
|
||||
LinkedList.prototype.addManyAfter = function (values, previousValue, compareFn) {
|
||||
if (compareFn === void 0) { compareFn = compare; }
|
||||
var previous = this.find(function (node) { return compareFn(node.value, previousValue); });
|
||||
return previous ? this.attachMany(values, previous, previous.next) : this.addManyTail(values);
|
||||
};
|
||||
LinkedList.prototype.addManyBefore = function (values, nextValue, compareFn) {
|
||||
if (compareFn === void 0) { compareFn = compare; }
|
||||
var next = this.find(function (node) { return compareFn(node.value, nextValue); });
|
||||
return next ? this.attachMany(values, next.previous, next) : this.addManyHead(values);
|
||||
};
|
||||
LinkedList.prototype.addManyByIndex = function (values, position) {
|
||||
if (position < 0)
|
||||
position += this.size;
|
||||
if (position <= 0)
|
||||
return this.addManyHead(values);
|
||||
if (position >= this.size)
|
||||
return this.addManyTail(values);
|
||||
var next = this.get(position);
|
||||
return this.attachMany(values, next.previous, next);
|
||||
};
|
||||
LinkedList.prototype.addManyHead = function (values) {
|
||||
var _this = this;
|
||||
return values.reduceRight(function (nodes, value) {
|
||||
nodes.unshift(_this.addHead(value));
|
||||
return nodes;
|
||||
}, []);
|
||||
};
|
||||
LinkedList.prototype.addManyTail = function (values) {
|
||||
var _this = this;
|
||||
return values.map(function (value) { return _this.addTail(value); });
|
||||
};
|
||||
LinkedList.prototype.drop = function () {
|
||||
var _this = this;
|
||||
return {
|
||||
byIndex: function (position) { return _this.dropByIndex(position); },
|
||||
byValue: function () {
|
||||
var params = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
params[_i] = arguments[_i];
|
||||
}
|
||||
return _this.dropByValue.apply(_this, params);
|
||||
},
|
||||
byValueAll: function () {
|
||||
var params = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
params[_i] = arguments[_i];
|
||||
}
|
||||
return _this.dropByValueAll.apply(_this, params);
|
||||
},
|
||||
head: function () { return _this.dropHead(); },
|
||||
tail: function () { return _this.dropTail(); },
|
||||
};
|
||||
};
|
||||
LinkedList.prototype.dropMany = function (count) {
|
||||
var _this = this;
|
||||
return {
|
||||
byIndex: function (position) { return _this.dropManyByIndex(count, position); },
|
||||
head: function () { return _this.dropManyHead(count); },
|
||||
tail: function () { return _this.dropManyTail(count); },
|
||||
};
|
||||
};
|
||||
LinkedList.prototype.dropByIndex = function (position) {
|
||||
if (position < 0)
|
||||
position += this.size;
|
||||
var current = this.get(position);
|
||||
return current ? this.detach(current) : undefined;
|
||||
};
|
||||
LinkedList.prototype.dropByValue = function (value, compareFn) {
|
||||
if (compareFn === void 0) { compareFn = compare; }
|
||||
var position = this.findIndex(function (node) { return compareFn(node.value, value); });
|
||||
return position < 0 ? undefined : this.dropByIndex(position);
|
||||
};
|
||||
LinkedList.prototype.dropByValueAll = function (value, compareFn) {
|
||||
if (compareFn === void 0) { compareFn = compare; }
|
||||
var dropped = [];
|
||||
for (var current = this.first, position = 0; current; position++, current = current.next) {
|
||||
if (compareFn(current.value, value)) {
|
||||
dropped.push(this.dropByIndex(position - dropped.length));
|
||||
}
|
||||
}
|
||||
return dropped;
|
||||
};
|
||||
LinkedList.prototype.dropHead = function () {
|
||||
var head = this.first;
|
||||
if (head) {
|
||||
this.first = head.next;
|
||||
if (this.first)
|
||||
this.first.previous = undefined;
|
||||
else
|
||||
this.last = undefined;
|
||||
this.size--;
|
||||
return head;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
LinkedList.prototype.dropTail = function () {
|
||||
var tail = this.last;
|
||||
if (tail) {
|
||||
this.last = tail.previous;
|
||||
if (this.last)
|
||||
this.last.next = undefined;
|
||||
else
|
||||
this.first = undefined;
|
||||
this.size--;
|
||||
return tail;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
LinkedList.prototype.dropManyByIndex = function (count, position) {
|
||||
if (count <= 0)
|
||||
return [];
|
||||
if (position < 0)
|
||||
position = Math.max(position + this.size, 0);
|
||||
else if (position >= this.size)
|
||||
return [];
|
||||
count = Math.min(count, this.size - position);
|
||||
var dropped = [];
|
||||
while (count--) {
|
||||
var current = this.get(position);
|
||||
dropped.push(this.detach(current));
|
||||
}
|
||||
return dropped;
|
||||
};
|
||||
LinkedList.prototype.dropManyHead = function (count) {
|
||||
if (count <= 0)
|
||||
return [];
|
||||
count = Math.min(count, this.size);
|
||||
var dropped = [];
|
||||
while (count--)
|
||||
dropped.unshift(this.dropHead());
|
||||
return dropped;
|
||||
};
|
||||
LinkedList.prototype.dropManyTail = function (count) {
|
||||
if (count <= 0)
|
||||
return [];
|
||||
count = Math.min(count, this.size);
|
||||
var dropped = [];
|
||||
while (count--)
|
||||
dropped.push(this.dropTail());
|
||||
return dropped;
|
||||
};
|
||||
LinkedList.prototype.find = function (predicate) {
|
||||
for (var current = this.first, position = 0; current; position++, current = current.next) {
|
||||
if (predicate(current, position, this))
|
||||
return current;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
LinkedList.prototype.findIndex = function (predicate) {
|
||||
for (var current = this.first, position = 0; current; position++, current = current.next) {
|
||||
if (predicate(current, position, this))
|
||||
return position;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
LinkedList.prototype.forEach = function (iteratorFn) {
|
||||
for (var node = this.first, position = 0; node; position++, node = node.next) {
|
||||
iteratorFn(node, position, this);
|
||||
}
|
||||
};
|
||||
LinkedList.prototype.get = function (position) {
|
||||
return this.find(function (_, index) { return position === index; });
|
||||
};
|
||||
LinkedList.prototype.indexOf = function (value, compareFn) {
|
||||
if (compareFn === void 0) { compareFn = compare; }
|
||||
return this.findIndex(function (node) { return compareFn(node.value, value); });
|
||||
};
|
||||
LinkedList.prototype.toArray = function () {
|
||||
var array = new Array(this.size);
|
||||
this.forEach(function (node, index) { return (array[index] = node.value); });
|
||||
return array;
|
||||
};
|
||||
LinkedList.prototype.toNodeArray = function () {
|
||||
var array = new Array(this.size);
|
||||
this.forEach(function (node, index) { return (array[index] = node); });
|
||||
return array;
|
||||
};
|
||||
LinkedList.prototype.toString = function (mapperFn) {
|
||||
if (mapperFn === void 0) { mapperFn = JSON.stringify; }
|
||||
return this.toArray()
|
||||
.map(function (value) { return mapperFn(value); })
|
||||
.join(' <-> ');
|
||||
};
|
||||
// Cannot use Generator type because of ng-packagr
|
||||
LinkedList.prototype[Symbol.iterator] = function () {
|
||||
var node, position;
|
||||
return __generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
node = this.first, position = 0;
|
||||
_a.label = 1;
|
||||
case 1:
|
||||
if (!node) return [3 /*break*/, 4];
|
||||
return [4 /*yield*/, node.value];
|
||||
case 2:
|
||||
_a.sent();
|
||||
_a.label = 3;
|
||||
case 3:
|
||||
position++, node = node.next;
|
||||
return [3 /*break*/, 1];
|
||||
case 4: return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
};
|
||||
return LinkedList;
|
||||
}());
|
||||
|
||||
/*
|
||||
* Public API Surface of utils
|
||||
*/
|
||||
|
||||
/**
|
||||
* Generated bundle index. Do not edit.
|
||||
*/
|
||||
|
||||
exports.LinkedList = LinkedList;
|
||||
exports.ListNode = ListNode;
|
||||
|
||||
Object.defineProperty(exports, '__esModule', { value: true });
|
||||
|
||||
})));
|
||||
//# sourceMappingURL=abp-utils.umd.js.map
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["en-CA"]={days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",monthsTitle:"Months",clear:"Clear",weekStart:0,format:"yyyy-mm-dd"},a.fn.datepicker.deprecated("This filename doesn't follow the convention, use bootstrap-datepicker.en-CA.js instead.")}(jQuery);
|
@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["ar-DZ"]={days:["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت","الأحد"],daysShort:["أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت","أحد"],daysMin:["ح","ن","ث","ع","خ","ج","س","ح"],months:["جانفي","فيفري","مارس","أفريل","ماي","جوان","جويليه","أوت","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],monthsShort:["جانفي","فيفري","مارس","أفريل","ماي","جوان","جويليه","أوت","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],today:"هذا اليوم",rtl:!0,monthsTitle:"أشهر",clear:"إزالة",format:"yyyy/mm/dd",weekStart:0}}(jQuery);
|
@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["ar-tn"]={days:["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت","الأحد"],daysShort:["أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت","أحد"],daysMin:["ح","ن","ث","ع","خ","ج","س","ح"],months:["جانفي","فيفري","مارس","أفريل","ماي","جوان","جويليه","أوت","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],monthsShort:["جانفي","فيفري","مارس","أفريل","ماي","جوان","جويليه","أوت","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],today:"هذا اليوم",rtl:!0}}(jQuery);
|
@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.ar={days:["الأحد","الاثنين","الثلاثاء","الأربعاء","الخميس","الجمعة","السبت","الأحد"],daysShort:["أحد","اثنين","ثلاثاء","أربعاء","خميس","جمعة","سبت","أحد"],daysMin:["ح","ن","ث","ع","خ","ج","س","ح"],months:["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],monthsShort:["يناير","فبراير","مارس","أبريل","مايو","يونيو","يوليو","أغسطس","سبتمبر","أكتوبر","نوفمبر","ديسمبر"],today:"هذا اليوم",rtl:!0}}(jQuery);
|
@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.az={days:["Bazar","Bazar ertəsi","Çərşənbə axşamı","Çərşənbə","Cümə axşamı","Cümə","Şənbə"],daysShort:["B.","B.e","Ç.a","Ç.","C.a","C.","Ş."],daysMin:["B.","B.e","Ç.a","Ç.","C.a","C.","Ş."],months:["Yanvar","Fevral","Mart","Aprel","May","İyun","İyul","Avqust","Sentyabr","Oktyabr","Noyabr","Dekabr"],monthsShort:["Yan","Fev","Mar","Apr","May","İyun","İyul","Avq","Sen","Okt","Noy","Dek"],today:"Bu gün",weekStart:1,clear:"Təmizlə",monthsTitle:"Aylar"}}(jQuery);
|
@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.bg={days:["Неделя","Понеделник","Вторник","Сряда","Четвъртък","Петък","Събота"],daysShort:["Нед","Пон","Вто","Сря","Чет","Пет","Съб"],daysMin:["Н","П","В","С","Ч","П","С"],months:["Януари","Февруари","Март","Април","Май","Юни","Юли","Август","Септември","Октомври","Ноември","Декември"],monthsShort:["Ян","Фев","Мар","Апр","Май","Юни","Юли","Авг","Сеп","Окт","Ное","Дек"],today:"днес"}}(jQuery);
|
@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.bm={days:["Kari","Ntɛnɛn","Tarata","Araba","Alamisa","Juma","Sibiri"],daysShort:["Kar","Ntɛ","Tar","Ara","Ala","Jum","Sib"],daysMin:["Ka","Nt","Ta","Ar","Al","Ju","Si"],months:["Zanwuyekalo","Fewuruyekalo","Marisikalo","Awirilikalo","Mɛkalo","Zuwɛnkalo","Zuluyekalo","Utikalo","Sɛtanburukalo","ɔkutɔburukalo","Nowanburukalo","Desanburukalo"],monthsShort:["Zan","Few","Mar","Awi","Mɛ","Zuw","Zul","Uti","Sɛt","ɔku","Now","Des"],today:"Bi",monthsTitle:"Kalo",clear:"Ka jɔsi",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
|
@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.bn={days:["রবিবার","সোমবার","মঙ্গলবার","বুধবার","বৃহস্পতিবার","শুক্রবার","শনিবার"],daysShort:["রবিবার","সোমবার","মঙ্গলবার","বুধবার","বৃহস্পতিবার","শুক্রবার","শনিবার"],daysMin:["রবি","সোম","মঙ্গল","বুধ","বৃহস্পতি","শুক্র","শনি"],months:["জানুয়ারী","ফেব্রুয়ারি","মার্চ","এপ্রিল","মে","জুন","জুলাই","অগাস্ট","সেপ্টেম্বর","অক্টোবর","নভেম্বর","ডিসেম্বর"],monthsShort:["জানুয়ারী","ফেব্রুয়ারি","মার্চ","এপ্রিল","মে","জুন","জুলাই","অগাস্ট","সেপ্টেম্বর","অক্টোবর","নভেম্বর","ডিসেম্বর"],today:"আজ",monthsTitle:"মাস",clear:"পরিষ্কার",weekStart:0,format:"mm/dd/yyyy"}}(jQuery);
|
@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.br={days:["Sul","Lun","Meurzh","Merc'her","Yaou","Gwener","Sadorn"],daysShort:["Sul","Lun","Meu.","Mer.","Yao.","Gwe.","Sad."],daysMin:["Su","L","Meu","Mer","Y","G","Sa"],months:["Genver","C'hwevrer","Meurzh","Ebrel","Mae","Mezheven","Gouere","Eost","Gwengolo","Here","Du","Kerzu"],monthsShort:["Genv.","C'hw.","Meur.","Ebre.","Mae","Mezh.","Goue.","Eost","Gwen.","Here","Du","Kerz."],today:"Hiziv",monthsTitle:"Miz",clear:"Dilemel",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
|
@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.bs={days:["Nedjelja","Ponedjeljak","Utorak","Srijeda","Četvrtak","Petak","Subota"],daysShort:["Ned","Pon","Uto","Sri","Čet","Pet","Sub"],daysMin:["N","Po","U","Sr","Č","Pe","Su"],months:["Januar","Februar","Mart","April","Maj","Juni","Juli","August","Septembar","Oktobar","Novembar","Decembar"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],today:"Danas",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
|
@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.ca={days:["diumenge","dilluns","dimarts","dimecres","dijous","divendres","dissabte"],daysShort:["dg.","dl.","dt.","dc.","dj.","dv.","ds."],daysMin:["dg","dl","dt","dc","dj","dv","ds"],months:["gener","febrer","març","abril","maig","juny","juliol","agost","setembre","octubre","novembre","desembre"],monthsShort:["gen.","febr.","març","abr.","maig","juny","jul.","ag.","set.","oct.","nov.","des."],today:"Avui",monthsTitle:"Mesos",clear:"Esborra",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
|
@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.cs={days:["Neděle","Pondělí","Úterý","Středa","Čtvrtek","Pátek","Sobota"],daysShort:["Ned","Pon","Úte","Stř","Čtv","Pát","Sob"],daysMin:["Ne","Po","Út","St","Čt","Pá","So"],months:["Leden","Únor","Březen","Duben","Květen","Červen","Červenec","Srpen","Září","Říjen","Listopad","Prosinec"],monthsShort:["Led","Úno","Bře","Dub","Kvě","Čer","Čnc","Srp","Zář","Říj","Lis","Pro"],today:"Dnes",clear:"Vymazat",monthsTitle:"Měsíc",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
|
@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.cy={days:["Sul","Llun","Mawrth","Mercher","Iau","Gwener","Sadwrn"],daysShort:["Sul","Llu","Maw","Mer","Iau","Gwe","Sad"],daysMin:["Su","Ll","Ma","Me","Ia","Gwe","Sa"],months:["Ionawr","Chewfror","Mawrth","Ebrill","Mai","Mehefin","Gorfennaf","Awst","Medi","Hydref","Tachwedd","Rhagfyr"],monthsShort:["Ion","Chw","Maw","Ebr","Mai","Meh","Gor","Aws","Med","Hyd","Tach","Rha"],today:"Heddiw"}}(jQuery);
|
@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.da={days:["Søndag","Mandag","Tirsdag","Onsdag","Torsdag","Fredag","Lørdag"],daysShort:["Søn","Man","Tir","Ons","Tor","Fre","Lør"],daysMin:["Sø","Ma","Ti","On","To","Fr","Lø"],months:["Januar","Februar","Marts","April","Maj","Juni","Juli","August","September","Oktober","November","December"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],today:"I Dag",weekStart:1,clear:"Nulstil",format:"dd/mm/yyyy",monthsTitle:"Måneder"}}(jQuery);
|
@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.de={days:["Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag"],daysShort:["So","Mo","Di","Mi","Do","Fr","Sa"],daysMin:["So","Mo","Di","Mi","Do","Fr","Sa"],months:["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],monthsShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",monthsTitle:"Monate",clear:"Löschen",weekStart:1,format:"dd.mm.yyyy"}}(jQuery);
|
@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates.el={days:["Κυριακή","Δευτέρα","Τρίτη","Τετάρτη","Πέμπτη","Παρασκευή","Σάββατο"],daysShort:["Κυρ","Δευ","Τρι","Τετ","Πεμ","Παρ","Σαβ"],daysMin:["Κυ","Δε","Τρ","Τε","Πε","Πα","Σα"],months:["Ιανουάριος","Φεβρουάριος","Μάρτιος","Απρίλιος","Μάιος","Ιούνιος","Ιούλιος","Αύγουστος","Σεπτέμβριος","Οκτώβριος","Νοέμβριος","Δεκέμβριος"],monthsShort:["Ιαν","Φεβ","Μαρ","Απρ","Μάι","Ιουν","Ιουλ","Αυγ","Σεπ","Οκτ","Νοε","Δεκ"],today:"Σήμερα",clear:"Καθαρισμός",weekStart:1,format:"d/m/yyyy"}}(jQuery);
|
@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["en-AU"]={days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",monthsTitle:"Months",clear:"Clear",weekStart:1,format:"d/mm/yyyy"}}(jQuery);
|
@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["en-CA"]={days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",monthsTitle:"Months",clear:"Clear",weekStart:0,format:"yyyy-mm-dd"}}(jQuery);
|
@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["en-GB"]={days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",monthsTitle:"Months",clear:"Clear",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
|
@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["en-IE"]={days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",monthsTitle:"Months",clear:"Clear",weekStart:1,format:"dd/mm/yyyy"}}(jQuery);
|
@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["en-NZ"]={days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",monthsTitle:"Months",clear:"Clear",weekStart:1,format:"d/mm/yyyy"}}(jQuery);
|
@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["en-US"]={days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",monthsTitle:"Months",clear:"Clear",weekStart:0,format:"m/d/yyyy"}}(jQuery);
|
@ -0,0 +1 @@
|
||||
!function(a){a.fn.datepicker.dates["en-ZA"]={days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",monthsTitle:"Months",clear:"Clear",weekStart:1,format:"yyyy/mm/d"}}(jQuery);
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user